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); }
private static int GetDepth(ExpressionRequest request, TypePairCount typePairCount) { if (typePairCount.TryGetValue(request, out int visitCount)) { visitCount = visitCount + 1; } typePairCount[request] = visitCount; return(visitCount); }
private List <MemberBinding> CreateMemberBindings(ExpressionRequest request, TypeMap typeMap, Expression instanceParameter, TypePairCount typePairCount, LetPropertyMaps letPropertyMaps) { 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) { 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); } }
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.CustomMapExpression != null) { return(typeMap.CustomMapExpression.ReplaceParameters(instanceParameter)); } return(CreateMapExpressionCore(request, instanceParameter, typePairCount, typeMap, letPropertyMaps)); }
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" + request.SourceType.Name); var expressions = new QueryExpressions(CreateMapExpressionCore(request, instanceParameter, typePairCount, letPropertyMaps, out var typeMap)); if (letPropertyMaps.Count > 0) { expressions = letPropertyMaps.GetSubQueryExpression(this, expressions.First, typeMap, request, instanceParameter, typePairCount); } 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) }); }
private LambdaExpression[] CreateMapExpression(ExpressionRequest request) => CreateMapExpression(request, new Dictionary <ExpressionRequest, int>(), new FirstPassLetPropertyMaps(_configurationProvider) );
public Expression CreateMapExpression(ExpressionRequest request, Expression instanceParameter, TypePairCount typePairCount, LetPropertyMaps letPropertyMaps) { return(CreateMapExpressionCore(request, instanceParameter, typePairCount, letPropertyMaps, out var _)); }
public MemberAssignment Build(IConfigurationProvider configuration, PropertyMap propertyMap, TypeMap propertyTypeMap, ExpressionRequest request, ExpressionResolutionResult result, IDictionary <ExpressionRequest, int> typePairCount, LetPropertyMaps letPropertyMaps) { var defaultDestination = Activator.CreateInstance(propertyMap.DestinationType); return(Bind(propertyMap.DestinationMember, Coalesce(result.ResolutionExpression, Constant(defaultDestination)))); }