Example #1
0
        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);
            }
        }
Example #2
0
        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);
        }
Example #3
0
        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);
                }
            }
        }
Example #4
0
        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);
        }
Example #5
0
        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);
            }
        }