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); }
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)); }
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)); }
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; }
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)); }
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); }
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); }
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); }
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); }
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); }
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); }