Exemplo n.º 1
0
        internal static Expression CreateMapExpression(IMappingEngine mappingEngine, ExpressionRequest request,
                                                       Expression instanceParameter, Internal.IDictionary <ExpressionRequest, int> typePairCount)
        {
            var typeMap = mappingEngine.ConfigurationProvider.ResolveTypeMap(request.SourceType,
                                                                             request.DestinationType);

            if (typeMap == null)
            {
                const string MessageFormat = "Missing map from {0} to {1}. Create using Mapper.CreateMap<{0}, {1}>.";

                var message = string.Format(MessageFormat, request.SourceType.Name, request.DestinationType.Name);

                throw new InvalidOperationException(message);
            }

            var bindings = CreateMemberBindings(mappingEngine, request, typeMap, instanceParameter, typePairCount);

            var parameterReplacer = new ParameterReplacementVisitor(instanceParameter);
            var visitor           = new NewFinderVisitor();
            var ctorExpr          = typeMap.ConstructExpression ?? Expression.Lambda(Expression.New(request.DestinationType));

            visitor.Visit(parameterReplacer.Visit(ctorExpr));

            var expression = Expression.MemberInit(
                visitor.NewExpression,
                bindings.ToArray()
                );

            return(expression);
        }
Exemplo n.º 2
0
        public LambdaExpression CreateMapExpression(ExpressionRequest request, Internal.IDictionary <ExpressionRequest, int> typePairCount)
        {
            // this is the input parameter of this expression with name <variableName>
            var instanceParameter = Expression.Parameter(request.SourceType, "dto");
            var total             = CreateMapExpression(request, instanceParameter, typePairCount);
            var delegateType      = typeof(Func <,>).MakeGenericType(request.SourceType, request.DestinationType);

            return(Expression.Lambda(delegateType, total, instanceParameter));
        }
Exemplo n.º 3
0
        public LambdaExpression CreateMapExpression(ExpressionRequest request, Internal.IDictionary <ExpressionRequest, int> typePairCount)
        {
            // this is the input parameter of this expression with name <variableName>
            ParameterExpression instanceParameter = Expression.Parameter(request.SourceType, "dto");

            var total = CreateMapExpression(request, instanceParameter, typePairCount);

            return(Expression.Lambda(total, instanceParameter));
        }
Exemplo n.º 4
0
 public MappingEngine(IConfigurationProvider configurationProvider, Internal.IDictionary <TypePair, IObjectMapper> objectMapperCache, Internal.IDictionary <ExpressionRequest, LambdaExpression> expressionCache,
                      Func <Type, object> serviceCtor)
 {
     ConfigurationProvider = configurationProvider;
     _objectMapperCache    = objectMapperCache;
     _expressionCache      = expressionCache;
     _serviceCtor          = serviceCtor;
     _mappers = configurationProvider.GetMappers();
     ConfigurationProvider.TypeMapCreated += ClearTypeMap;
 }
Exemplo n.º 5
0
        private static LambdaExpression CreateMapExpression(IMappingEngine mappingEngine, TypePair typePair,
                                                            Internal.IDictionary <TypePair, int> typePairCount)
        {
            // this is the input parameter of this expression with name <variableName>
            ParameterExpression instanceParameter = Expression.Parameter(typePair.SourceType, "dto");

            var total = CreateMapExpression(mappingEngine, typePair, instanceParameter, typePairCount);

            return(Expression.Lambda(total, instanceParameter));
        }
Exemplo n.º 6
0
        public Expression CreateMapExpression(ExpressionRequest request,
                                              Expression instanceParameter, Internal.IDictionary <ExpressionRequest, int> typePairCount)
        {
            var typeMap = ConfigurationProvider.ResolveTypeMap(request.SourceType,
                                                               request.DestinationType);

            if (typeMap == null)
            {
                const string MessageFormat = "Missing map from {0} to {1}. Create using Mapper.CreateMap<{0}, {1}>.";

                var message = string.Format(MessageFormat, request.SourceType.Name, request.DestinationType.Name);

                throw new InvalidOperationException(message);
            }

            var parameterReplacer = instanceParameter is ParameterExpression ? new ParameterReplacementVisitor(instanceParameter) : null;
            var customProjection  = typeMap.CustomProjection;

            if (customProjection != null)
            {
                return(parameterReplacer == null ? customProjection.Body : parameterReplacer.Visit(customProjection.Body));
            }

            var bindings = CreateMemberBindings(request, typeMap, instanceParameter, typePairCount);

            Expression constructorExpression = typeMap.DestinationConstructorExpression(instanceParameter);

            if (parameterReplacer != null)
            {
                constructorExpression = parameterReplacer.Visit(constructorExpression);
            }
            var visitor = new NewFinderVisitor();

            visitor.Visit(constructorExpression);

            var expression = Expression.MemberInit(
                visitor.NewExpression,
                bindings.ToArray()
                );

            return(expression);
        }
        private static MemberAssignment BindMappedTypeExpression(IMappingEngine mappingEngine, PropertyMap propertyMap,
                                                                 ExpressionRequest request, ExpressionResolutionResult result, Internal.IDictionary <ExpressionRequest, int> typePairCount)
        {
            var transformedExpression = ((IMappingEngineRunner)mappingEngine).CreateMapExpression(request, result.ResolutionExpression, typePairCount);

            // Handles null source property so it will not create an object with possible non-nullable propeerties
            // which would result in an exception.
            if (mappingEngine.ConfigurationProvider.AllowNullDestinationValues)
            {
                var expressionNull = Expression.Constant(null, propertyMap.DestinationPropertyType);
                transformedExpression =
                    Expression.Condition(Expression.NotEqual(result.ResolutionExpression, Expression.Constant(null)),
                                         transformedExpression, expressionNull);
            }

            return(Expression.Bind(propertyMap.DestinationProperty.MemberInfo, transformedExpression));
        }
 public MemberAssignment Build(IMappingEngine mappingEngine, PropertyMap propertyMap, TypeMap propertyTypeMap,
                               ExpressionRequest request, ExpressionResolutionResult result, Internal.IDictionary <ExpressionRequest, int> typePairCount)
 {
     return(BindMappedTypeExpression(mappingEngine, propertyMap, request, result, typePairCount));
 }
        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.FindTypeMapFor(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)
                {
                    throw new AutoMapperMappingException("Unable to create a map expression from " + result.Type + " to " + propertyMap.DestinationPropertyType);
                }

                var bindExpression = binder.Build(mappingEngine, propertyMap, propertyTypeMap, propertyRequest, result, typePairCount);

                bindings.Add(bindExpression);
            }
            return(bindings);
        }
Exemplo n.º 10
0
        private List <MemberBinding> CreateMemberBindings(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.MembersToExpand.Contains(propertyMap.DestinationProperty.MemberInfo))
                {
                    continue;
                }

                var propertyTypeMap = ConfigurationProvider.ResolveTypeMap(result.Type,
                                                                           propertyMap.DestinationPropertyType);
                var propertyRequest = new ExpressionRequest(result.Type, propertyMap.DestinationPropertyType, request.MembersToExpand);

                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(this, propertyMap, propertyTypeMap, propertyRequest, result, typePairCount);

                bindings.Add(bindExpression);
            }
            return(bindings);
        }
Exemplo n.º 11
0
        private static MemberAssignment BindEnumerableExpression(IMappingEngine mappingEngine, PropertyMap propertyMap,
                                                                 ExpressionRequest request, ExpressionResolutionResult result, Internal.IDictionary <ExpressionRequest, int> typePairCount)
        {
            MemberAssignment bindExpression;
            Type             destinationListType = GetDestinationListTypeFor(propertyMap);

            var sourceListType = result.Type.IsArray ? result.Type.GetElementType() : result.Type.GetGenericArguments().First();
            var listTypePair   = new ExpressionRequest(sourceListType, destinationListType, request.MembersToExpand);

            var selectExpression = result.ResolutionExpression;

            if (sourceListType != destinationListType)
            {
                var transformedExpression = ((IMappingEngineRunner)mappingEngine).CreateMapExpression(listTypePair, typePairCount);
                selectExpression = Expression.Call(
                    typeof(Enumerable),
                    "Select",
                    new[] { sourceListType, destinationListType },
                    result.ResolutionExpression,
                    transformedExpression);
            }

            if (typeof(IList <>).MakeGenericType(destinationListType)
                .IsAssignableFrom(propertyMap.DestinationPropertyType)
                ||
                typeof(ICollection <>).MakeGenericType(destinationListType)
                .IsAssignableFrom(propertyMap.DestinationPropertyType))
            {
                // Call .ToList() on IEnumerable
                var toListCallExpression = GetToListCallExpression(propertyMap, destinationListType, selectExpression);

                bindExpression = Expression.Bind(propertyMap.DestinationProperty.MemberInfo, toListCallExpression);
            }
            else if (propertyMap.DestinationPropertyType.IsArray)
            {
                // Call .ToArray() on IEnumerable
                MethodCallExpression toArrayCallExpression = Expression.Call(
                    typeof(Enumerable),
                    "ToArray",
                    new[] { destinationListType },
                    selectExpression);
                bindExpression = Expression.Bind(propertyMap.DestinationProperty.MemberInfo, toArrayCallExpression);
            }
            else
            {
                // destination type implements ienumerable, but is not an ilist. allow deferred enumeration
                bindExpression = Expression.Bind(propertyMap.DestinationProperty.MemberInfo, selectExpression);
            }
            return(bindExpression);
        }
Exemplo n.º 12
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);
        }
Exemplo n.º 13
0
        private static Expression CreateMapExpression(IMappingEngine mappingEngine, TypePair typePair, Expression instanceParameter, Internal.IDictionary <TypePair, int> typePairCount)
        {
            var typeMap = mappingEngine.ConfigurationProvider.FindTypeMapFor(typePair.SourceType,
                                                                             typePair.DestinationType);

            if (typeMap == null)
            {
                const string MessageFormat = "Missing map from {0} to {1}. Create using Mapper.CreateMap<{0}, {1}>.";

                var message = string.Format(MessageFormat, typePair.SourceType.Name, typePair.DestinationType.Name);

                throw new InvalidOperationException(message);
            }

            var bindings = CreateMemberBindings(mappingEngine, typePair, typeMap, instanceParameter, typePairCount);

            Expression total = Expression.MemberInit(
                Expression.New(typePair.DestinationType),
                bindings.ToArray()
                );

            return(total);
        }
Exemplo n.º 14
0
        private static MemberAssignment BindMappedTypeExpression(IMappingEngine mappingEngine, PropertyMap propertyMap, ExpressionResolutionResult result, MemberInfo destinationMember, Internal.IDictionary <TypePair, int> typePairCount)
        {
            MemberAssignment bindExpression;
            var memberPair            = new TypePair(result.Type, propertyMap.DestinationPropertyType);
            var transformedExpression = CreateMapExpression(mappingEngine, memberPair,
                                                            result.ResolutionExpression,
                                                            typePairCount);

            // Handles null source property so it will not create an object with possible non-nullable propeerties
            // which would result in an exception.
            if (mappingEngine.ConfigurationProvider.MapNullSourceValuesAsNull)
            {
                var expressionNull = Expression.Constant(null, propertyMap.DestinationPropertyType);
                transformedExpression =
                    Expression.Condition(Expression.NotEqual(result.ResolutionExpression, Expression.Constant(null)),
                                         transformedExpression, expressionNull);
            }

            bindExpression = Expression.Bind(destinationMember, transformedExpression);
            return(bindExpression);
        }