public void Seal() { var derivedMaps = new List <Tuple <TypePair, TypeMap> >(); var redirectedTypes = new List <Tuple <TypePair, TypePair> >(); foreach (var typeMap in _userDefinedTypeMaps.Values) { typeMap.Seal(); _typeMapPlanCache.AddOrUpdate(typeMap.Types, typeMap, (_, _2) => typeMap); if (typeMap.DestinationTypeOverride != null) { redirectedTypes.Add(Tuple.Create(typeMap.Types, new TypePair(typeMap.SourceType, typeMap.DestinationTypeOverride))); } derivedMaps.AddRange(GetDerivedTypeMaps(typeMap).Select(derivedMap => Tuple.Create(new TypePair(derivedMap.SourceType, typeMap.DestinationType), derivedMap))); } foreach (var redirectedType in redirectedTypes) { var derivedMap = FindTypeMapFor(redirectedType.Item2); if (derivedMap != null) { _typeMapPlanCache.AddOrUpdate(redirectedType.Item1, derivedMap, (_, _2) => derivedMap); } } foreach (var derivedMap in derivedMaps) { _typeMapPlanCache.GetOrAdd(derivedMap.Item1, _ => derivedMap.Item2); } }
private static List <MemberBinding> CreateMemberBindings(IMappingEngine mappingEngine, TypePair typePair, TypeMap typeMap, Expression instanceParameter, Internal.IDictionary <TypePair, int> typePairCount) { var bindings = new List <MemberBinding>(); var visitCount = typePairCount.AddOrUpdate(typePair, 0, (tp, i) => i + 1); if (visitCount >= typeMap.MaxDepth) { return(bindings); } foreach (var propertyMap in typeMap.GetPropertyMaps().Where(pm => pm.CanResolveValue())) { var result = ResolveExpression(propertyMap, typePair.SourceType, instanceParameter); var destinationMember = propertyMap.DestinationProperty.MemberInfo; MemberAssignment bindExpression; if (propertyMap.DestinationPropertyType.IsNullableType() && !result.Type.IsNullableType()) { bindExpression = BindNullableExpression(propertyMap, result, destinationMember); } else if (propertyMap.DestinationPropertyType.IsAssignableFrom(result.Type)) { bindExpression = BindAssignableExpression(destinationMember, result); } else if (propertyMap.DestinationPropertyType.GetInterfaces().Any(t => t.Name == "IEnumerable") && propertyMap.DestinationPropertyType != typeof(string)) { bindExpression = BindEnumerableExpression(mappingEngine, propertyMap, result, destinationMember, typePairCount); } else if (result.Type != propertyMap.DestinationPropertyType && // avoid nullable etc. propertyMap.DestinationPropertyType.BaseType != typeof(ValueType) && propertyMap.DestinationPropertyType.BaseType != typeof(Enum)) { bindExpression = BindMappedTypeExpression(mappingEngine, propertyMap, result, destinationMember, typePairCount); } else { throw new AutoMapperMappingException("Unable to create a map expression from " + result.Type + " to " + propertyMap.DestinationPropertyType); } bindings.Add(bindExpression); } return(bindings); }
public void Seal() { foreach (var typeMap in _userDefinedTypeMaps.Values) { typeMap.Seal(); var typePair = new TypePair(typeMap.SourceType, typeMap.DestinationType); _typeMapPlanCache.AddOrUpdate(typePair, typeMap, (_, _2) => typeMap); if (typeMap.DestinationTypeOverride != null) { var includedDerivedType = new TypePair(typeMap.SourceType, typeMap.DestinationTypeOverride); var derivedMap = FindTypeMapFor(includedDerivedType); if (derivedMap != null) { _typeMapPlanCache.AddOrUpdate(typePair, derivedMap, (_, _2) => derivedMap); } } foreach (var derivedMap in GetDerivedTypeMaps(typeMap)) { _typeMapPlanCache.AddOrUpdate(new TypePair(derivedMap.SourceType, typeMap.DestinationType), derivedMap, (_, _2) => derivedMap); } } }
private static List <MemberBinding> CreateMemberBindings(IMappingEngine mappingEngine, ExpressionRequest request, TypeMap typeMap, Expression instanceParameter, Internal.IDictionary <ExpressionRequest, int> typePairCount) { var bindings = new List <MemberBinding>(); var visitCount = typePairCount.AddOrUpdate(request, 0, (tp, i) => i + 1); if (visitCount >= typeMap.MaxDepth) { return(bindings); } foreach (var propertyMap in typeMap.GetPropertyMaps().Where(pm => pm.CanResolveValue())) { var result = ResolveExpression(propertyMap, request.SourceType, instanceParameter); if (propertyMap.ExplicitExpansion && !request.IncludedMembers.Contains(propertyMap.DestinationProperty.Name)) { continue; } var propertyTypeMap = mappingEngine.ConfigurationProvider.ResolveTypeMap(result.Type, propertyMap.DestinationPropertyType); var propertyRequest = new ExpressionRequest(result.Type, propertyMap.DestinationPropertyType, request.IncludedMembers); var binder = Binders.FirstOrDefault(b => b.IsMatch(propertyMap, propertyTypeMap, result)); if (binder == null) { var message = $"Unable to create a map expression from {propertyMap.SourceMember.DeclaringType.Name}.{propertyMap.SourceMember.Name} ({result.Type}) to {propertyMap.DestinationProperty.MemberInfo.DeclaringType.Name}.{propertyMap.DestinationProperty.Name} ({propertyMap.DestinationPropertyType})"; throw new AutoMapperMappingException(message); } var bindExpression = binder.Build(mappingEngine, propertyMap, propertyTypeMap, propertyRequest, result, typePairCount); bindings.Add(bindExpression); } return(bindings); }
object IMappingEngineRunner.Map(ResolutionContext context) { try { var contextTypePair = new TypePair(context.SourceType, context.DestinationType); Func <TypePair, IObjectMapper> missFunc = tp => ConfigurationProvider.GetMappers().FirstOrDefault(mapper => mapper.IsMatch(context)); IObjectMapper mapperToUse = _objectMapperCache.GetOrAdd(contextTypePair, missFunc); if (mapperToUse == null || (context.Options.CreateMissingTypeMaps && !mapperToUse.IsMatch(context))) { if (context.Options.CreateMissingTypeMaps) { var typeMap = ConfigurationProvider.CreateTypeMap(context.SourceType, context.DestinationType); context = context.CreateTypeContext(typeMap, context.SourceValue, context.DestinationValue, context.SourceType, context.DestinationType); mapperToUse = missFunc(contextTypePair); if (mapperToUse == null) { throw new AutoMapperMappingException(context, "Unsupported mapping."); } _objectMapperCache.AddOrUpdate(contextTypePair, mapperToUse, (tp, mapper) => mapperToUse); } else { if (context.SourceValue != null) { throw new AutoMapperMappingException(context, "Missing type map configuration or unsupported mapping."); } return(ObjectCreator.CreateDefaultValue(context.DestinationType)); } } return(mapperToUse.Map(context, this)); } catch (AutoMapperMappingException) { throw; } catch (Exception ex) { throw new AutoMapperMappingException(context, ex); } }