Beispiel #1
0
        public Expression NewExpression(Expression instanceParameter, LetPropertyMaps letPropertyMaps)
        {
            var parameters = CtorParams.Select(map =>
            {
                var result = new ExpressionResolutionResult(instanceParameter, Ctor.DeclaringType);

                var matchingExpressionConverter =
                    ExpressionResultConverters.FirstOrDefault(c => c.CanGetExpressionResolutionResult(result, map));

                result = matchingExpressionConverter?.GetExpressionResolutionResult(result, map, letPropertyMaps)
                         ?? throw new AutoMapperMappingException($"Unable to generate the instantiation expression for the constructor {Ctor}: no expression could be mapped for constructor parameter '{map.Parameter}'.", null, TypeMap.Types);

                return(result);
            });

            return(New(Ctor, parameters.Select(p => p.ResolutionExpression)));
        }
        public ExpressionResolutionResult GetExpressionResolutionResult(
            ExpressionResolutionResult expressionResolutionResult, IMemberMap propertyMap, LetPropertyMaps letPropertyMaps)
        {
            Expression subQueryMarker;

            if ((subQueryMarker = letPropertyMaps.GetSubQueryMarker()) != null)
            {
                return(new ExpressionResolutionResult(subQueryMarker, subQueryMarker.Type));
            }
            var currentChild     = propertyMap.CustomMapExpression.ReplaceParameters(expressionResolutionResult.ResolutionExpression);
            var currentChildType = currentChild.Type;

            return(new ExpressionResolutionResult(currentChild, currentChildType));
        }
        private static MemberAssignment BindMappedTypeExpression(IConfigurationProvider configuration, PropertyMap propertyMap, ExpressionRequest request, ExpressionResolutionResult result, IDictionary <ExpressionRequest, int> typePairCount, LetPropertyMaps letPropertyMaps)
        {
            var transformedExpression = configuration.ExpressionBuilder.CreateMapExpression(request, result.ResolutionExpression, typePairCount, letPropertyMaps);

            if (transformedExpression == null)
            {
                return(null);
            }
            // Handles null source property so it will not create an object with possible non-nullable properties
            // which would result in an exception.
            if (propertyMap.TypeMap.Profile.AllowNullDestinationValues && !propertyMap.AllowNull && !(result.ResolutionExpression is ParameterExpression))
            {
                transformedExpression = result.ResolutionExpression.IfNullElse(Constant(null, transformedExpression.Type), transformedExpression);
            }

            return(Bind(propertyMap.DestinationProperty, transformedExpression));
        }
 public ExpressionResolutionResult GetExpressionResolutionResult(ExpressionResolutionResult expressionResolutionResult, IMemberMap propertyMap, LetPropertyMaps letPropertyMaps)
 => new ExpressionResolutionResult(propertyMap.SourceMembers.MemberAccesses(propertyMap.CheckCustomSource(expressionResolutionResult, letPropertyMaps)));
Beispiel #5
0
        private static ExpressionResolutionResult ResolveExpression(PropertyMap propertyMap, Type currentType,
                                                                    Expression instanceParameter, LetPropertyMaps letPropertyMaps)
        {
            var result = new ExpressionResolutionResult(instanceParameter, currentType);

            var matchingExpressionConverter =
                ExpressionResultConverters.FirstOrDefault(c => c.CanGetExpressionResolutionResult(result, propertyMap));

            result = matchingExpressionConverter?.GetExpressionResolutionResult(result, propertyMap, letPropertyMaps)
                     ?? throw new Exception("Can't resolve this to Queryable Expression");

            if (propertyMap.NullSubstitute != null && result.Type.IsNullableType())
            {
                var currentChild     = result.ResolutionExpression;
                var currentChildType = result.Type;
                var nullSubstitute   = propertyMap.NullSubstitute;

                var newParameter = result.ResolutionExpression;
                var converter    = new NullSubstitutionConversionVisitor(newParameter, nullSubstitute);

                currentChild     = converter.Visit(currentChild);
                currentChildType = currentChildType.GetTypeOfNullable();

                return(new ExpressionResolutionResult(currentChild, currentChildType));
            }

            return(result);
        }
Beispiel #6
0
        private Expression CreateMapExpressionCore(ExpressionRequest request, Expression instanceParameter, TypePairCount typePairCount, TypeMap typeMap, LetPropertyMaps letPropertyMaps)
        {
            var bindings = new List <MemberBinding>();
            var depth    = GetDepth(request, typePairCount);

            if (typeMap.MaxDepth > 0 && depth >= typeMap.MaxDepth)
            {
                if (typeMap.Profile.AllowNullDestinationValues)
                {
                    return(null);
                }
            }
            else
            {
                bindings = CreateMemberBindings(request, typeMap, instanceParameter, typePairCount, letPropertyMaps);
            }
            Expression constructorExpression = DestinationConstructorExpression(typeMap, instanceParameter);

            if (instanceParameter is ParameterExpression)
            {
                constructorExpression = ((LambdaExpression)constructorExpression).ReplaceParameters(instanceParameter);
            }
            var visitor = new NewFinderVisitor();

            visitor.Visit(constructorExpression);

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

            return(expression);
        }
Beispiel #7
0
 public Expression CreateMapExpression(ExpressionRequest request, Expression instanceParameter, TypePairCount typePairCount, LetPropertyMaps letPropertyMaps)
 {
     return(CreateMapExpressionCore(request, instanceParameter, typePairCount, letPropertyMaps, out var _));
 }
Beispiel #8
0
 public MemberAssignment Build(IConfigurationProvider configuration, PropertyMap propertyMap, TypeMap propertyTypeMap, ExpressionRequest request, ExpressionResolutionResult result, IDictionary <ExpressionRequest, int> typePairCount, LetPropertyMaps letPropertyMaps) =>
 Bind(propertyMap.DestinationProperty, Convert(result.ResolutionExpression, propertyMap.DestinationPropertyType));
        private ExpressionResolutionResult ResolveExpression(IMemberMap propertyMap, Type currentType, Expression instanceParameter, LetPropertyMaps letPropertyMaps)
        {
            var result = new ExpressionResolutionResult(instanceParameter, currentType);
            var matchingExpressionConverter = _configurationProvider.ResultConverters.FirstOrDefault(c => c.CanGetExpressionResolutionResult(result, propertyMap));

            if (matchingExpressionConverter == null)
            {
                ThrowCannotMap(propertyMap, result);
                return(null);
            }
            result = matchingExpressionConverter.GetExpressionResolutionResult(result, propertyMap, letPropertyMaps);
            if (propertyMap.NullSubstitute != null && result.ResolutionExpression is MemberExpression && (result.Type.IsNullableType() || result.Type == typeof(string)))
            {
                return(new ExpressionResolutionResult(propertyMap.NullSubstitute(result.ResolutionExpression)));
            }
            return(result);
        }
        public Expression NewExpression(ConstructorMap constructorMap, ExpressionRequest request, Expression instanceParameter, TypePairCount typePairCount, LetPropertyMaps letPropertyMaps)
        {
            var parameters = constructorMap.CtorParams.Select(map =>
            {
                var resolvedSource = ResolveExpression(map, request.SourceType, instanceParameter, letPropertyMaps);
                var types          = new TypePair(resolvedSource.Type, map.DestinationType);
                var typeMap        = _configurationProvider.ResolveTypeMap(types);
                if (typeMap == null)
                {
                    if (types.DestinationType.IsAssignableFrom(types.SourceType))
                    {
                        return(resolvedSource.ResolutionExpression);
                    }
                    ThrowCannotMap(map, resolvedSource);
                }
                var newRequest = new ExpressionRequest(types.SourceType, types.DestinationType, request.MembersToExpand, request);
                return(CreateMapExpressionCore(newRequest, resolvedSource.ResolutionExpression, typePairCount, typeMap, letPropertyMaps));
            });

            return(New(constructorMap.Ctor, parameters));
        }
        private LambdaExpression DestinationConstructorExpression(ExpressionRequest request, Expression instanceParameter, TypePairCount typePairCount, TypeMap typeMap, LetPropertyMaps letPropertyMaps)
        {
            var ctorExpr = typeMap.CustomCtorExpression;

            if (ctorExpr != null)
            {
                return(ctorExpr);
            }
            var newExpression = typeMap.ConstructorMap?.CanResolve == true
                ? NewExpression(typeMap.ConstructorMap, request, instanceParameter, typePairCount, letPropertyMaps)
                : New(typeMap.DestinationTypeToUse);

            return(Lambda(newExpression));
        }
        private Expression CreateMapExpressionCore(ExpressionRequest request, Expression instanceParameter, TypePairCount typePairCount, TypeMap typeMap, LetPropertyMaps letPropertyMaps)
        {
            if (typeMap.CustomMapExpression != null)
            {
                return(typeMap.CustomMapExpression.ReplaceParameters(instanceParameter));
            }
            var memberBindings = new List <MemberBinding>();
            var depth          = GetDepth(request, typePairCount);

            if (typeMap.MaxDepth > 0 && depth >= typeMap.MaxDepth)
            {
                if (typeMap.Profile.AllowNullDestinationValues)
                {
                    return(null);
                }
            }
            else
            {
                memberBindings = CreateMemberBindings();
            }
            var constructorExpressionLambda = DestinationConstructorExpression(request, instanceParameter, typePairCount, typeMap, letPropertyMaps);
            var constructorExpression       = instanceParameter is ParameterExpression?constructorExpressionLambda.ReplaceParameters(instanceParameter) : constructorExpressionLambda.Body;

            var expression = MemberInit((NewExpression)constructorExpression, memberBindings);

            return(expression);

            List <MemberBinding> CreateMemberBindings()
            {
                var bindings = new List <MemberBinding>();

                foreach (var propertyMap in typeMap.PropertyMaps
                         .Where(pm => (!pm.ExplicitExpansion || request.MembersToExpand.Contains(pm.DestinationMember)) &&
                                pm.CanResolveValue && ReflectionHelper.CanBeSet(pm.DestinationMember))
                         .OrderBy(pm => pm.DestinationName))
                {
                    var propertyExpression = new PropertyExpression(propertyMap);
                    letPropertyMaps.Push(propertyExpression);

                    CreateMemberBinding(propertyExpression);

                    letPropertyMaps.Pop();
                }
                return(bindings);

                void CreateMemberBinding(PropertyExpression propertyExpression)
                {
                    var propertyMap = propertyExpression.PropertyMap;
                    var result      = ResolveExpression(propertyMap, request.SourceType, instanceParameter, letPropertyMaps);

                    propertyExpression.Expression = result.NonMarkerExpression;
                    var propertyTypeMap = _configurationProvider.ResolveTypeMap(result.Type, propertyMap.DestinationType);
                    var propertyRequest = new ExpressionRequest(result.Type, propertyMap.DestinationType, request.MembersToExpand, request);

                    if (propertyRequest.AlreadyExists && depth >= _configurationProvider.RecursiveQueriesMaxDepth)
                    {
                        return;
                    }
                    var binder = _configurationProvider.Binders.FirstOrDefault(b => b.IsMatch(propertyMap, propertyTypeMap, result));

                    if (binder == null)
                    {
                        ThrowCannotMap(propertyMap, result);
                        return;
                    }
                    var bindExpression = binder.Build(_configurationProvider, propertyMap, propertyTypeMap, propertyRequest, result, typePairCount, letPropertyMaps);

                    if (bindExpression == null)
                    {
                        return;
                    }
                    var rhs = propertyMap.ValueTransformers
                              .Concat(typeMap.ValueTransformers)
                              .Concat(typeMap.Profile.ValueTransformers)
                              .Where(vt => vt.IsMatch(propertyMap))
                              .Aggregate(bindExpression.Expression, (current, vtConfig) => ToType(vtConfig.TransformerExpression.ReplaceParameters(ToType(current, vtConfig.ValueType)), propertyMap.DestinationType));

                    bindExpression = bindExpression.Update(rhs);

                    bindings.Add(bindExpression);
                }
            }
        }
        public ExpressionResolutionResult GetExpressionResolutionResult(
            ExpressionResolutionResult expressionResolutionResult, IMemberMap propertyMap, LetPropertyMaps letPropertyMaps)
        {
            var mapFrom = propertyMap.CustomMapExpression;

            if (!IsSubQuery() || letPropertyMaps.ConfigurationProvider.ResolveTypeMap(propertyMap.SourceType, propertyMap.DestinationType) == null)
            {
                return(new ExpressionResolutionResult(mapFrom.ReplaceParameters(propertyMap.CheckCustomSource(expressionResolutionResult, letPropertyMaps))));
            }
            if (propertyMap.CustomSource == null)
            {
                return(new ExpressionResolutionResult(letPropertyMaps.GetSubQueryMarker(mapFrom), mapFrom));
            }
            var newMapFrom = Lambda(mapFrom.ReplaceParameters(propertyMap.CustomSource.Body), propertyMap.CustomSource.Parameters);

            return(new ExpressionResolutionResult(letPropertyMaps.GetSubQueryMarker(newMapFrom), newMapFrom));

            bool IsSubQuery()
            {
                if (!(mapFrom.Body is MethodCallExpression methodCall))
                {
                    return(false);
                }
                var method = methodCall.Method;

                return(method.IsStatic && method.DeclaringType == typeof(Enumerable));
            }
        }
Beispiel #14
0
        private Expression CreateMapExpressionCore(ExpressionRequest request, Expression instanceParameter, TypePairCount typePairCount, TypeMap typeMap, LetPropertyMaps letPropertyMaps)
        {
            var memberBindings = new List <MemberBinding>();
            var depth          = GetDepth(request, typePairCount);

            if (typeMap.MaxDepth > 0 && depth >= typeMap.MaxDepth)
            {
                if (typeMap.Profile.AllowNullDestinationValues)
                {
                    return(null);
                }
            }
            else
            {
                memberBindings = CreateMemberBindings();
            }
            Expression constructorExpression = DestinationConstructorExpression(typeMap, instanceParameter, letPropertyMaps);

            if (instanceParameter is ParameterExpression)
            {
                constructorExpression = ((LambdaExpression)constructorExpression).ReplaceParameters(instanceParameter);
            }
            var visitor = new NewFinderVisitor();

            visitor.Visit(constructorExpression);

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

            return(expression);

            List <MemberBinding> CreateMemberBindings()
            {
                var bindings = new List <MemberBinding>();

                foreach (var propertyMap in typeMap.PropertyMaps
                         .Where(pm => (!pm.ExplicitExpansion || request.MembersToExpand.Contains(pm.DestinationMember)) &&
                                pm.CanResolveValue && ReflectionHelper.CanBeSet(pm.DestinationMember))
                         .OrderBy(pm => pm.DestinationName))
                {
                    var propertyExpression = new PropertyExpression(propertyMap);
                    letPropertyMaps.Push(propertyExpression);

                    CreateMemberBinding(propertyExpression);

                    letPropertyMaps.Pop();
                }
                return(bindings);

                void CreateMemberBinding(PropertyExpression propertyExpression)
                {
                    var propertyMap = propertyExpression.PropertyMap;
                    var result      = ResolveExpression(propertyMap, request.SourceType, instanceParameter, letPropertyMaps);

                    propertyExpression.Expression = result.ResolutionExpression;
                    var propertyTypeMap = _configurationProvider.ResolveTypeMap(result.Type, propertyMap.DestinationType);
                    var propertyRequest = new ExpressionRequest(result.Type, propertyMap.DestinationType, request.MembersToExpand, request);

                    if (propertyRequest.AlreadyExists && depth >= _configurationProvider.RecursiveQueriesMaxDepth)
                    {
                        return;
                    }
                    var binder = _configurationProvider.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.DestinationMember.DeclaringType?.Name}.{propertyMap.DestinationName} ({propertyMap.DestinationType})";
                        throw new AutoMapperMappingException(message, null, typeMap.Types, typeMap, propertyMap);
                    }
                    var bindExpression = binder.Build(_configurationProvider, propertyMap, propertyTypeMap, propertyRequest, result, typePairCount, letPropertyMaps);

                    if (bindExpression == null)
                    {
                        return;
                    }
                    var rhs = propertyMap.ValueTransformers
                              .Concat(typeMap.ValueTransformers)
                              .Concat(typeMap.Profile.ValueTransformers)
                              .Where(vt => vt.IsMatch(propertyMap))
                              .Aggregate(bindExpression.Expression, (current, vtConfig) => ToType(ReplaceParameters(vtConfig.TransformerExpression, ToType(current, vtConfig.ValueType)), propertyMap.DestinationType));

                    bindExpression = bindExpression.Update(rhs);

                    bindings.Add(bindExpression);
                }
            }
        }
        public static Expression CheckCustomSource(this IMemberMap memberMap, ExpressionResolutionResult expressionResolutionResult, LetPropertyMaps letPropertyMaps)
        {
            var customSource = memberMap.ProjectToCustomSource;

            if (customSource == null)
            {
                return(expressionResolutionResult.ResolutionExpression);
            }
            return(customSource.IsMemberPath() ?
                   customSource.ReplaceParameters(expressionResolutionResult.ResolutionExpression) :
                   letPropertyMaps.GetSubQueryMarker(customSource));
        }
 private Expression CreateMapExpressionCore(ExpressionRequest request, Expression instanceParameter, TypePairCount typePairCount, LetPropertyMaps letPropertyMaps, out TypeMap typeMap)
 {
     typeMap = _configurationProvider.ResolveTypeMap(request.SourceType, request.DestinationType) ?? throw QueryMapperHelper.MissingMapException(request.SourceType, request.DestinationType);
     return(CreateMapExpressionCore(request, instanceParameter, typePairCount, typeMap, letPropertyMaps));
 }
Beispiel #17
0
        private List <MemberBinding> CreateMemberBindings(ExpressionRequest request, TypeMap typeMap, Expression instanceParameter, TypePairCount typePairCount, LetPropertyMaps letPropertyMaps)
        {
            var bindings = new List <MemberBinding>();

            foreach (var propertyMap in typeMap.GetPropertyMaps()
                     .Where(pm => (!pm.ExplicitExpansion || request.MembersToExpand.Contains(pm.DestinationProperty)) &&
                            pm.CanResolveValue() && ReflectionHelper.CanBeSet(pm.DestinationProperty))
                     .OrderBy(pm => pm.DestinationProperty.Name))
            {
                letPropertyMaps.Push(propertyMap);

                CreateMemberBinding(propertyMap);

                letPropertyMaps.Pop();
            }

            return(bindings);

            void CreateMemberBinding(PropertyMap propertyMap)
            {
                var result          = ResolveExpression(propertyMap, request.SourceType, instanceParameter, letPropertyMaps);
                var propertyTypeMap = _configurationProvider.ResolveTypeMap(result.Type, propertyMap.DestinationPropertyType);
                var propertyRequest = new ExpressionRequest(result.Type, propertyMap.DestinationPropertyType, request.MembersToExpand, request);

                if (propertyRequest.AlreadyExists)
                {
                    return;
                }
                var binder = _configurationProvider.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.DeclaringType?.Name}.{propertyMap.DestinationProperty.Name} ({propertyMap.DestinationPropertyType})";
                    throw new AutoMapperMappingException(message, null, typeMap.Types, typeMap, propertyMap);
                }
                var bindExpression = binder.Build(_configurationProvider, propertyMap, propertyTypeMap, propertyRequest, result, typePairCount, letPropertyMaps);

                if (bindExpression == null)
                {
                    return;
                }
                var rhs = propertyMap.ValueTransformers
                          .Concat(typeMap.ValueTransformers)
                          .Concat(typeMap.Profile.ValueTransformers)
                          .Where(vt => vt.IsMatch(propertyMap))
                          .Aggregate(bindExpression.Expression, (current, vtConfig) => ToType(ReplaceParameters(vtConfig.TransformerExpression, ToType(current, vtConfig.ValueType)), propertyMap.DestinationPropertyType));

                bindExpression = bindExpression.Update(rhs);

                bindings.Add(bindExpression);
            }
        }
        private Expression CreateMapExpressionCore(ExpressionRequest request, Expression instanceParameter, TypePairCount typePairCount, TypeMap typeMap, LetPropertyMaps letPropertyMaps)
        {
            if (typeMap.CustomMapExpression != null)
            {
                return(typeMap.CustomMapExpression.ReplaceParameters(instanceParameter));
            }
            var memberBindings = new List <MemberBinding>();
            var depth          = GetDepth();

            if (typeMap.MaxDepth > 0 && depth >= typeMap.MaxDepth)
            {
                if (typeMap.Profile.AllowNullDestinationValues)
                {
                    return(null);
                }
            }
            else
            {
                memberBindings = CreateMemberBindings();
            }
            var constructorExpression = CreateDestination();
            var expression            = MemberInit(constructorExpression, memberBindings);

            return(expression);

            int GetDepth()
            {
                if (typePairCount.TryGetValue(request, out int visitCount))
                {
                    visitCount++;
                }
                typePairCount[request] = visitCount;
                return(visitCount);
            }

            List <MemberBinding> CreateMemberBindings()
            {
                var bindings = new List <MemberBinding>();

                foreach (var propertyMap in typeMap.PropertyMaps
                         .Where
                         (
                             pm =>
                             (
                                 !pm.ExplicitExpansion ||
                                 request.MembersToExpand.Any
                                 (
                                     member => member.Equals(pm.DestinationMember) &&
                                     member.ReflectedType == typeMap.DestinationType
                                 )
                             ) &&
                             pm.CanResolveValue && pm.DestinationMember.CanBeSet()
                         )
                         .OrderBy(pm => pm.DestinationName))
                {
                    var propertyExpression = new PropertyExpression(propertyMap);
                    letPropertyMaps.Push(propertyExpression);

                    CreateMemberBinding(propertyExpression);

                    letPropertyMaps.Pop();
                }
                return(bindings);

                void CreateMemberBinding(PropertyExpression propertyExpression)
                {
                    var propertyMap = propertyExpression.PropertyMap;
                    var result      = ResolveExpression(propertyMap);

                    propertyExpression.Expression = result.NonMarkerExpression;
                    var propertyTypeMap = _configurationProvider.ResolveTypeMap(result.Type, propertyMap.DestinationType);
                    var propertyRequest = new ExpressionRequest(result.Type, propertyMap.DestinationType, request.MembersToExpand, request);

                    if (propertyRequest.AlreadyExists && depth >= _configurationProvider.RecursiveQueriesMaxDepth)
                    {
                        return;
                    }
                    var binder = _configurationProvider.Binders.FirstOrDefault(b => b.IsMatch(propertyMap, propertyTypeMap, result));

                    if (binder == null)
                    {
                        ThrowCannotMap(propertyMap, result);
                    }

                    var bindExpression = binder?.Build(_configurationProvider, propertyMap, propertyTypeMap, propertyRequest, result, typePairCount, letPropertyMaps);

                    if (bindExpression == null)
                    {
                        return;
                    }
                    var rhs = propertyMap.ValueTransformers
                              .Concat(typeMap.ValueTransformers)
                              .Concat(typeMap.Profile.ValueTransformers)
                              .Where(vt => vt.IsMatch(propertyMap))
                              .Aggregate(bindExpression.Expression, (current, vtConfig) => ToType(vtConfig.TransformerExpression.ReplaceParameters(ToType(current, vtConfig.ValueType)), propertyMap.DestinationType));

                    bindExpression = bindExpression.Update(rhs);

                    bindings.Add(bindExpression);
                }
            }

            ExpressionResolutionResult ResolveExpression(IMemberMap propertyMap)
            {
                var result  = new ExpressionResolutionResult(instanceParameter, request.SourceType);
                var result1 = result;
                var matchingExpressionConverter = _configurationProvider.ResultConverters.FirstOrDefault(c => c.CanGetExpressionResolutionResult(result1, propertyMap));

                if (matchingExpressionConverter == null)
                {
                    ThrowCannotMap(propertyMap, result);
                }

                if (matchingExpressionConverter != null)
                {
                    result = matchingExpressionConverter.GetExpressionResolutionResult(result, propertyMap,
                                                                                       letPropertyMaps);
                }
                if (propertyMap.NullSubstitute != null && result.ResolutionExpression is MemberExpression && (result.Type.IsNullableType() || result.Type == typeof(string)))
                {
                    return(new ExpressionResolutionResult(propertyMap.NullSubstitute(result.ResolutionExpression)));
                }
                return(result);
            }

            NewExpression CreateDestination()
            {
                var ctorExpr = typeMap.CustomCtorExpression;

                if (ctorExpr != null)
                {
                    return((NewExpression)ctorExpr.ReplaceParameters(instanceParameter));
                }
                return(typeMap.ConstructorMap?.CanResolve == true?ConstructorMapping(typeMap.ConstructorMap) : New(typeMap.DestinationTypeToUse));

                NewExpression ConstructorMapping(ConstructorMap constructorMap) => New(constructorMap.Ctor, constructorMap.CtorParams.Select(CreateConstructorParameter));

                Expression CreateConstructorParameter(ConstructorParameterMap map)
                {
                    var resolvedSource = ResolveExpression(map);
                    var types          = new TypePair(resolvedSource.Type, map.DestinationType);
                    var typeMap        = _configurationProvider.ResolveTypeMap(types);

                    if (typeMap == null)
                    {
                        if (types.DestinationType.IsAssignableFrom(types.SourceType))
                        {
                            return(resolvedSource.ResolutionExpression);
                        }
                        ThrowCannotMap(map, resolvedSource);
                    }
                    var newRequest = new ExpressionRequest(types.SourceType, types.DestinationType, request.MembersToExpand, request);

                    return(CreateMapExpressionCore(newRequest, resolvedSource.ResolutionExpression, typePairCount, typeMap, letPropertyMaps));
                }
            }
        }
Beispiel #19
0
 public ExpressionResolutionResult GetExpressionResolutionResult(ExpressionResolutionResult expressionResolutionResult, PropertyMap propertyMap, LetPropertyMaps letPropertyMaps) =>
 new ExpressionResolutionResult(
     Convert(MakeMemberAccess(expressionResolutionResult.ResolutionExpression, propertyMap.SourceMember), propertyMap.DestinationPropertyType),
     propertyMap.DestinationPropertyType);
Beispiel #20
0
        public ExpressionResolutionResult GetExpressionResolutionResult(
            ExpressionResolutionResult expressionResolutionResult, PropertyMap propertyMap, LetPropertyMaps letPropertyMaps)
        {
            Expression subQueryMarker;

            if ((subQueryMarker = letPropertyMaps.GetSubQueryMarker()) != null)
            {
                return(new ExpressionResolutionResult(subQueryMarker, subQueryMarker.Type));
            }
            return(ExpressionResolutionResult(expressionResolutionResult, propertyMap.CustomMapExpression));
        }
Beispiel #21
0
        private Expression CreateMapExpressionCore(ExpressionRequest request, Expression instanceParameter, TypePairCount typePairCount, LetPropertyMaps letPropertyMaps, out TypeMap typeMap)
        {
            typeMap = _configurationProvider.ResolveTypeMap(request.SourceType, request.DestinationType);

            if (typeMap == null)
            {
                throw QueryMapperHelper.MissingMapException(request.SourceType, request.DestinationType);
            }

            if (typeMap.CustomProjection != null)
            {
                return(typeMap.CustomProjection.ReplaceParameters(instanceParameter));
            }
            return(CreateMapExpressionCore(request, instanceParameter, typePairCount, typeMap, letPropertyMaps));
        }
Beispiel #22
0
        private static MemberAssignment BindEnumerableExpression(IConfigurationProvider configuration, PropertyMap propertyMap, ExpressionRequest request, ExpressionResolutionResult result, IDictionary <ExpressionRequest, int> typePairCount, LetPropertyMaps letPropertyMaps)
        {
            var expression = result.ResolutionExpression;

            if (propertyMap.DestinationPropertyType != expression.Type)
            {
                var destinationListType    = ElementTypeHelper.GetElementType(propertyMap.DestinationPropertyType);
                var sourceListType         = ElementTypeHelper.GetElementType(propertyMap.SourceType);
                var listTypePair           = new ExpressionRequest(sourceListType, destinationListType, request.MembersToExpand, request);
                var transformedExpressions = configuration.ExpressionBuilder.CreateMapExpression(listTypePair, typePairCount, letPropertyMaps.New());
                if (transformedExpressions == null)
                {
                    return(null);
                }
                expression = transformedExpressions.Aggregate(expression, (source, lambda) => Select(source, lambda));
            }

            return(Expression.Bind(propertyMap.DestinationProperty, expression));
        }
Beispiel #23
0
        private List <MemberBinding> CreateMemberBindings(ExpressionRequest request,
                                                          TypeMap typeMap,
                                                          Expression instanceParameter, TypePairCount typePairCount, LetPropertyMaps letPropertyMaps)
        {
            var bindings = new List <MemberBinding>();

            foreach (var propertyMap in typeMap.GetPropertyMaps().Where(pm => pm.CanResolveValue()))
            {
                letPropertyMaps.Push(propertyMap);

                CreateMemberBinding(propertyMap);

                letPropertyMaps.Pop();
            }
            return(bindings);

            void CreateMemberBinding(PropertyMap propertyMap)
            {
                var result = ResolveExpression(propertyMap, request.SourceType, instanceParameter, letPropertyMaps);

                if (propertyMap.ExplicitExpansion && !request.MembersToExpand.Contains(propertyMap.DestinationProperty))
                {
                    return;
                }
                var propertyTypeMap = _configurationProvider.ResolveTypeMap(result.Type,
                                                                            propertyMap.DestinationPropertyType);
                var propertyRequest = new ExpressionRequest(result.Type, propertyMap.DestinationPropertyType, request.MembersToExpand, request);

                if (!propertyRequest.AlreadyExists)
                {
                    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.DeclaringType?.Name}.{propertyMap.DestinationProperty.Name} ({propertyMap.DestinationPropertyType})";

                        throw new AutoMapperMappingException(message, null, typeMap.Types, typeMap, propertyMap);
                    }

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

                    if (bindExpression != null)
                    {
                        bindings.Add(bindExpression);
                    }
                }
            }
        }
        private static MemberAssignment BindEnumerableExpression(IConfigurationProvider configuration, PropertyMap propertyMap, ExpressionRequest request, ExpressionResolutionResult result, IDictionary <ExpressionRequest, int> typePairCount, LetPropertyMaps letPropertyMaps)
        {
            var destinationListType = ElementTypeHelper.GetElementType(propertyMap.DestinationType);
            var sourceListType      = ElementTypeHelper.GetElementType(propertyMap.SourceType);
            var expression          = result.ResolutionExpression;

            if (sourceListType != destinationListType)
            {
                var listTypePair           = new ExpressionRequest(sourceListType, destinationListType, request.MembersToExpand, request);
                var transformedExpressions = configuration.ExpressionBuilder.CreateMapExpression(listTypePair, typePairCount, letPropertyMaps.New());
                if (transformedExpressions == null)
                {
                    return(null);
                }
                expression = transformedExpressions.Aggregate(expression, Select);
            }
            if (!propertyMap.DestinationType.IsAssignableFrom(expression.Type))
            {
                var convertFunction = propertyMap.DestinationType.IsArray ? nameof(Enumerable.ToArray) : nameof(Enumerable.ToList);
                expression = Expression.Call(typeof(Enumerable), convertFunction, new[] { destinationListType }, expression);
            }
            return(Expression.Bind(propertyMap.DestinationMember, expression));
        }
Beispiel #25
0
        public LambdaExpression[] CreateMapExpression(ExpressionRequest request, TypePairCount typePairCount, LetPropertyMaps letPropertyMaps)
        {
            // this is the input parameter of this expression with name <variableName>
            var instanceParameter = Parameter(request.SourceType, "dto");
            var expressions       = new QueryExpressions(CreateMapExpressionCore(request, instanceParameter, typePairCount, letPropertyMaps, out var typeMap));

#if NET45
            if (letPropertyMaps.Count > 0)
            {
                expressions = letPropertyMaps.GetSubQueryExpression(this, expressions.First, typeMap, request, instanceParameter, typePairCount);
            }
#endif
            if (expressions.First == null)
            {
                return(null);
            }
            var firstLambda = Lambda(expressions.First, instanceParameter);
            if (expressions.Second == null)
            {
                return(new[] { firstLambda });
            }
            return(new[] { firstLambda, Lambda(expressions.Second, expressions.SecondParameter) });
        }
Beispiel #26
0
        public MemberAssignment Build(IConfigurationProvider configuration, PropertyMap propertyMap, TypeMap propertyTypeMap, ExpressionRequest request, ExpressionResolutionResult result, IDictionary <ExpressionRequest, int> typePairCount, LetPropertyMaps letPropertyMaps)
        {
            var defaultDestination = Activator.CreateInstance(propertyMap.DestinationPropertyType);

            return(Bind(propertyMap.DestinationProperty, Coalesce(result.ResolutionExpression, Constant(defaultDestination))));
        }
 public MemberAssignment Build(IConfigurationProvider configuration, PropertyMap propertyMap, TypeMap propertyTypeMap, ExpressionRequest request, ExpressionResolutionResult result, IDictionary <ExpressionRequest, int> typePairCount, LetPropertyMaps letPropertyMaps)
 => BindMappedTypeExpression(configuration, propertyMap, request, result, typePairCount, letPropertyMaps);
 public ExpressionResolutionResult GetExpressionResolutionResult(ExpressionResolutionResult expressionResolutionResult, IMemberMap propertyMap, LetPropertyMaps letPropertyMaps)
 => propertyMap.SourceMembers.Aggregate(expressionResolutionResult, ExpressionResolutionResult);
 public ExpressionResolutionResult GetExpressionResolutionResult(ExpressionResolutionResult expressionResolutionResult, PropertyMap propertyMap, LetPropertyMaps letPropertyMaps)
 => ExpressionResolutionResult(expressionResolutionResult, propertyMap.SourceMembers);
Beispiel #30
0
        private ExpressionResolutionResult ResolveExpression(IMemberMap propertyMap, Type currentType, Expression instanceParameter, LetPropertyMaps letPropertyMaps)
        {
            var result = new ExpressionResolutionResult(instanceParameter, currentType);
            var matchingExpressionConverter = _configurationProvider.ResultConverters.FirstOrDefault(c => c.CanGetExpressionResolutionResult(result, propertyMap));

            if (matchingExpressionConverter == null)
            {
                ThrowCannotMap(propertyMap, result);
                return(null);
            }
            result = matchingExpressionConverter.GetExpressionResolutionResult(result, propertyMap, letPropertyMaps);
            if (propertyMap.NullSubstitute != null && result.Type.IsNullableType())
            {
                var currentChild     = result.ResolutionExpression;
                var currentChildType = result.Type;
                var nullSubstitute   = propertyMap.NullSubstitute;

                var newParameter = result.ResolutionExpression;
                var converter    = new NullSubstitutionConversionVisitor(newParameter, nullSubstitute);

                currentChild     = converter.Visit(currentChild);
                currentChildType = currentChildType.GetTypeOfNullable();

                return(new ExpressionResolutionResult(currentChild, currentChildType));
            }

            return(result);
        }