public Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider, Expression sourceExpression, Expression destExpression, Expression contextExpression) { var sourceElementType = TypeHelper.GetElementType(sourceExpression.Type); var destElementType = TypeHelper.GetElementType(destExpression.Type); if (destExpression.Type.IsAssignableFrom(sourceExpression.Type) && typeMapRegistry.GetTypeMap(new TypePair(sourceElementType, destElementType)) == null) { // return (TDestination[]) source; var convertExpr = Convert(sourceExpression, destElementType.MakeArrayType()); if (configurationProvider.AllowNullCollections) { return(convertExpr); } // return (TDestination[]) source ?? new TDestination[0]; return(Coalesce(convertExpr, NewArrayBounds(destElementType, Constant(0)))); } var ifNullExpr = configurationProvider.AllowNullCollections ? (Expression)Constant(null) : NewArrayBounds(destElementType, Constant(0)); var mapExpr = Call(null, Map2MethodInfo.MakeGenericMethod(sourceElementType, destElementType), sourceExpression, contextExpression); // return (source == null) ? ifNullExpr : Map<TSourceElement, TDestElement>(source, context); return(Condition(Equal(sourceExpression, Constant(null)), ifNullExpr, mapExpr)); }
private static Expression BuildValueResolverFunc(PropertyMap propertyMap, TypeMapRegistry typeMapRegistry, ParameterExpression srcParam, ParameterExpression ctxtParam) { Expression valueResolverFunc; var valueResolverConfig = propertyMap.ValueResolverConfig; var typeMap = propertyMap.TypeMap; if (valueResolverConfig != null) { Expression ctor; Type resolverType; if (valueResolverConfig.Instance != null) { ctor = Constant(valueResolverConfig.Instance); resolverType = valueResolverConfig.Instance.GetType(); } else { ctor = Call(MakeMemberAccess(ctxtParam, typeof (ResolutionContext).GetProperty("Options")), typeof (MappingOperationOptions).GetMethod("CreateInstance") .MakeGenericMethod(valueResolverConfig.Type) ); resolverType = valueResolverConfig.Type; } Expression sourceFunc; if (valueResolverConfig.SourceMember != null) { sourceFunc = valueResolverConfig.SourceMember.ReplaceParameters(srcParam); } else if (valueResolverConfig.SourceMemberName != null) { sourceFunc = MakeMemberAccess(srcParam, typeMap.SourceType.GetFieldOrProperty(valueResolverConfig.SourceMemberName)); } else { sourceFunc = srcParam; } valueResolverFunc = Convert(Call(ToType(ctor, resolverType), resolverType.GetMethod("Resolve"), sourceFunc, ctxtParam), propertyMap.DestinationPropertyType); } else if (propertyMap.CustomValue != null) { valueResolverFunc = Constant(propertyMap.CustomValue); } else if (propertyMap.CustomResolver != null) { valueResolverFunc = propertyMap.CustomResolver.ReplaceParameters(srcParam, ctxtParam); } else if (propertyMap.CustomExpression != null) { valueResolverFunc = propertyMap.CustomExpression.ReplaceParameters(srcParam).IfNotNull(); } else if (propertyMap.SourceMembers.Any() && propertyMap.SourceType != null ) { var last = propertyMap.SourceMembers.Last(); var pi = last.MemberInfo as PropertyInfo; if (pi != null && pi.GetGetMethod(true) == null) { valueResolverFunc = Default(last.MemberType); } else { valueResolverFunc = propertyMap.SourceMembers.Aggregate( (Expression) srcParam, (inner, getter) => getter.MemberInfo is MethodInfo ? getter.MemberInfo.IsStatic() ? Call(null, (MethodInfo) getter.MemberInfo, inner) : (Expression) Call(inner, (MethodInfo) getter.MemberInfo) : MakeMemberAccess(getter.MemberInfo.IsStatic() ? null : inner, getter.MemberInfo) ); valueResolverFunc = valueResolverFunc.IfNotNull(); } } else if (propertyMap.SourceMember != null) { valueResolverFunc = MakeMemberAccess(srcParam, propertyMap.SourceMember); } else { valueResolverFunc = Throw(Constant(new Exception("I done blowed up"))); } if (propertyMap.DestinationPropertyType == typeof (string) && valueResolverFunc.Type != typeof (string) && typeMapRegistry.GetTypeMap(new TypePair(valueResolverFunc.Type, propertyMap.DestinationPropertyType)) == null) { valueResolverFunc = Call(valueResolverFunc, valueResolverFunc.Type.GetMethod("ToString", new Type[0])); } if (propertyMap.NullSubstitute != null) { Expression value = Constant(propertyMap.NullSubstitute); if (propertyMap.NullSubstitute.GetType() != propertyMap.DestinationPropertyType) value = Convert(value, propertyMap.DestinationPropertyType); valueResolverFunc = MakeBinary(ExpressionType.Coalesce, valueResolverFunc, value); } else if (!typeMap.Profile.AllowNullDestinationValues) { var toCreate = propertyMap.SourceType ?? propertyMap.DestinationPropertyType; if (!toCreate.GetTypeInfo().IsValueType) { valueResolverFunc = MakeBinary(ExpressionType.Coalesce, valueResolverFunc, Convert(Call( typeof (ObjectCreator).GetMethod("CreateNonNullValue"), Constant(toCreate) ), propertyMap.SourceType)); } } return valueResolverFunc; }
private static Expression CreatePropertyMapFunc( PropertyMap propertyMap, IConfigurationProvider configurationProvider, TypeMapRegistry typeMapRegistry, ParameterExpression srcParam, ParameterExpression destParam, ParameterExpression ctxtParam, ref ParameterExpression propertyContext) { var valueResolverExpr = BuildValueResolverFunc(propertyMap, typeMapRegistry, srcParam, ctxtParam); var destMember = MakeMemberAccess(destParam, propertyMap.DestinationProperty.MemberInfo); Expression getter; var pi = propertyMap.DestinationProperty.MemberInfo as PropertyInfo; if (pi != null && pi.GetGetMethod(true) == null) { getter = Default(propertyMap.DestinationPropertyType); } else { getter = destMember; } var destValueExpr = propertyMap.UseDestinationValue ? getter : Default(propertyMap.TypeMap.DestinationType); if (propertyMap.SourceType != null && propertyMap.DestinationPropertyType != null) { var typePair = new TypePair(propertyMap.SourceType, propertyMap.DestinationPropertyType); var typeMap = typeMapRegistry.GetTypeMap(typePair); if (typeMap != null && (typeMap.TypeConverterType != null || typeMap.CustomMapper != null)) { if(!typeMap.Sealed) typeMap.Seal(typeMapRegistry, configurationProvider); valueResolverExpr = typeMap.MapExpression.ReplaceParameters(valueResolverExpr, destValueExpr, ctxtParam); } else { var match = configurationProvider.GetMappers().FirstOrDefault(m => m.IsMatch(typePair)); var expressionMapper = match as IObjectMapExpression; if (expressionMapper != null) valueResolverExpr = expressionMapper.MapExpression(valueResolverExpr, destValueExpr, ctxtParam); else valueResolverExpr = SetMap(propertyMap, valueResolverExpr, destValueExpr, ref propertyContext); } } else { valueResolverExpr = SetMap(propertyMap, valueResolverExpr, destValueExpr, ref propertyContext); } if (propertyMap.Condition != null) { valueResolverExpr = Condition( Invoke( propertyMap.Condition, srcParam, destParam, ToType(valueResolverExpr, propertyMap.Condition.Parameters[2].Type), ToType(destValueExpr, propertyMap.Condition.Parameters[2].Type), ctxtParam ), Convert(valueResolverExpr, propertyMap.DestinationPropertyType), destValueExpr ); } Expression mapperExpr; if (propertyMap.DestinationProperty.MemberInfo is FieldInfo) { mapperExpr = propertyMap.SourceType != propertyMap.DestinationPropertyType ? Assign(destMember, Convert(valueResolverExpr, propertyMap.DestinationPropertyType)) : Assign(getter, valueResolverExpr); } else { var setter = ((PropertyInfo) propertyMap.DestinationProperty.MemberInfo).GetSetMethod(true); if (setter == null) { mapperExpr = valueResolverExpr; } else { mapperExpr = Assign(destMember, propertyMap.SourceType != propertyMap.DestinationPropertyType ? Convert(valueResolverExpr, propertyMap.DestinationPropertyType) : valueResolverExpr); } } if (propertyMap.PreCondition != null) { mapperExpr = IfThen( Invoke(propertyMap.PreCondition, srcParam, ctxtParam), mapperExpr ); } return mapperExpr; }
private static Expression BuildValueResolverFunc(PropertyMap propertyMap, TypeMapRegistry typeMapRegistry, ParameterExpression srcParam, ParameterExpression ctxtParam) { Expression valueResolverFunc; var valueResolverConfig = propertyMap.ValueResolverConfig; var typeMap = propertyMap.TypeMap; if (valueResolverConfig != null) { Expression ctor; Type resolverType; if (valueResolverConfig.Instance != null) { ctor = Constant(valueResolverConfig.Instance); resolverType = valueResolverConfig.Instance.GetType(); } else { ctor = Call(MakeMemberAccess(ctxtParam, typeof(ResolutionContext).GetProperty("Options")), typeof(MappingOperationOptions).GetMethod("CreateInstance") .MakeGenericMethod(valueResolverConfig.Type) ); resolverType = valueResolverConfig.Type; } Expression sourceFunc; if (valueResolverConfig.SourceMember != null) { sourceFunc = valueResolverConfig.SourceMember.ReplaceParameters(srcParam); } else if (valueResolverConfig.SourceMemberName != null) { sourceFunc = MakeMemberAccess(srcParam, typeMap.SourceType.GetFieldOrProperty(valueResolverConfig.SourceMemberName)); } else { sourceFunc = srcParam; } valueResolverFunc = Convert(Call(ToType(ctor, resolverType), resolverType.GetMethod("Resolve"), sourceFunc, ctxtParam), propertyMap.DestinationPropertyType); } else if (propertyMap.CustomValue != null) { valueResolverFunc = Constant(propertyMap.CustomValue); } else if (propertyMap.CustomResolver != null) { valueResolverFunc = propertyMap.CustomResolver.ReplaceParameters(srcParam, ctxtParam); } else if (propertyMap.CustomExpression != null) { valueResolverFunc = propertyMap.CustomExpression.ReplaceParameters(srcParam).IfNotNull(); } else if (propertyMap.SourceMembers.Any() && propertyMap.SourceType != null ) { var last = propertyMap.SourceMembers.Last(); var pi = last.MemberInfo as PropertyInfo; if (pi != null && pi.GetGetMethod(true) == null) { valueResolverFunc = Default(last.MemberType); } else { valueResolverFunc = propertyMap.SourceMembers.Aggregate( (Expression)srcParam, (inner, getter) => getter.MemberInfo is MethodInfo ? getter.MemberInfo.IsStatic() ? Call(null, (MethodInfo)getter.MemberInfo, inner) : (Expression)Call(inner, (MethodInfo)getter.MemberInfo) : MakeMemberAccess(getter.MemberInfo.IsStatic() ? null : inner, getter.MemberInfo) ); valueResolverFunc = valueResolverFunc.IfNotNull(); } } else if (propertyMap.SourceMember != null) { valueResolverFunc = MakeMemberAccess(srcParam, propertyMap.SourceMember); } else { valueResolverFunc = Throw(Constant(new Exception("I done blowed up"))); } if (propertyMap.DestinationPropertyType == typeof(string) && valueResolverFunc.Type != typeof(string) && typeMapRegistry.GetTypeMap(new TypePair(valueResolverFunc.Type, propertyMap.DestinationPropertyType)) == null) { valueResolverFunc = Call(valueResolverFunc, valueResolverFunc.Type.GetMethod("ToString", new Type[0])); } if (propertyMap.NullSubstitute != null) { Expression value = Constant(propertyMap.NullSubstitute); if (propertyMap.NullSubstitute.GetType() != propertyMap.DestinationPropertyType) { value = Convert(value, propertyMap.DestinationPropertyType); } valueResolverFunc = MakeBinary(ExpressionType.Coalesce, valueResolverFunc, value); } else if (!typeMap.Profile.AllowNullDestinationValues) { var toCreate = propertyMap.SourceType ?? propertyMap.DestinationPropertyType; if (!toCreate.GetTypeInfo().IsValueType) { valueResolverFunc = MakeBinary(ExpressionType.Coalesce, valueResolverFunc, Convert(Call( typeof(ObjectCreator).GetMethod("CreateNonNullValue"), Constant(toCreate) ), propertyMap.SourceType)); } } return(valueResolverFunc); }
private static Expression CreatePropertyMapFunc( PropertyMap propertyMap, IConfigurationProvider configurationProvider, TypeMapRegistry typeMapRegistry, ParameterExpression srcParam, ParameterExpression destParam, ParameterExpression ctxtParam, ref ParameterExpression propertyContext) { var valueResolverExpr = BuildValueResolverFunc(propertyMap, typeMapRegistry, srcParam, ctxtParam); var destMember = MakeMemberAccess(destParam, propertyMap.DestinationProperty.MemberInfo); Expression getter; var pi = propertyMap.DestinationProperty.MemberInfo as PropertyInfo; if (pi != null && pi.GetGetMethod(true) == null) { getter = Default(propertyMap.DestinationPropertyType); } else { getter = destMember; } var destValueExpr = propertyMap.UseDestinationValue ? getter : Default(propertyMap.TypeMap.DestinationType); if (propertyMap.SourceType != null && propertyMap.DestinationPropertyType != null) { var typePair = new TypePair(propertyMap.SourceType, propertyMap.DestinationPropertyType); var typeMap = typeMapRegistry.GetTypeMap(typePair); if (typeMap != null && (typeMap.TypeConverterType != null || typeMap.CustomMapper != null)) { if (!typeMap.Sealed) { typeMap.Seal(typeMapRegistry, configurationProvider); } valueResolverExpr = typeMap.MapExpression.ReplaceParameters(valueResolverExpr, destValueExpr, ctxtParam); } else { var match = configurationProvider.GetMappers().FirstOrDefault(m => m.IsMatch(typePair)); var expressionMapper = match as IObjectMapExpression; if (expressionMapper != null) { valueResolverExpr = expressionMapper.MapExpression(valueResolverExpr, destValueExpr, ctxtParam); } else { valueResolverExpr = SetMap(propertyMap, valueResolverExpr, destValueExpr, ref propertyContext); } } } else { valueResolverExpr = SetMap(propertyMap, valueResolverExpr, destValueExpr, ref propertyContext); } if (propertyMap.Condition != null) { valueResolverExpr = Condition( Invoke( propertyMap.Condition, srcParam, destParam, ToType(valueResolverExpr, propertyMap.Condition.Parameters[2].Type), ToType(destValueExpr, propertyMap.Condition.Parameters[2].Type), ctxtParam ), Convert(valueResolverExpr, propertyMap.DestinationPropertyType), destValueExpr ); } Expression mapperExpr; if (propertyMap.DestinationProperty.MemberInfo is FieldInfo) { mapperExpr = propertyMap.SourceType != propertyMap.DestinationPropertyType ? Assign(destMember, Convert(valueResolverExpr, propertyMap.DestinationPropertyType)) : Assign(getter, valueResolverExpr); } else { var setter = ((PropertyInfo)propertyMap.DestinationProperty.MemberInfo).GetSetMethod(true); if (setter == null) { mapperExpr = valueResolverExpr; } else { mapperExpr = Assign(destMember, propertyMap.SourceType != propertyMap.DestinationPropertyType ? Convert(valueResolverExpr, propertyMap.DestinationPropertyType) : valueResolverExpr); } } if (propertyMap.PreCondition != null) { mapperExpr = IfThen( Invoke(propertyMap.PreCondition, srcParam, ctxtParam), mapperExpr ); } return(mapperExpr); }
public Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider, PropertyMap propertyMap, Expression sourceExpression, Expression destExpression, Expression contextExpression) { var sourceElementType = TypeHelper.GetElementType(sourceExpression.Type); var destElementType = TypeHelper.GetElementType(destExpression.Type); if (destExpression.Type.IsAssignableFrom(sourceExpression.Type) && typeMapRegistry.GetTypeMap(new TypePair(sourceElementType, destElementType)) == null) { // return (TDestination[]) source; var convertExpr = Convert(sourceExpression, destElementType.MakeArrayType()); if (configurationProvider.AllowNullCollections) { return(convertExpr); } // return (TDestination[]) source ?? new TDestination[0]; return(Coalesce(convertExpr, NewArrayBounds(destElementType, Constant(0)))); } var ifNullExpr = configurationProvider.AllowNullCollections ? (Expression)Constant(null) : NewArrayBounds(destElementType, Constant(0)); var itemParam = Parameter(sourceElementType, "item"); var itemExpr = typeMapRegistry.MapItemExpr(configurationProvider, propertyMap, sourceExpression.Type, destExpression.Type, itemParam, contextExpression); //var count = source.Count(); //var array = new TDestination[count]; //int i = 0; //foreach (var item in source) // array[i++] = newItemFunc(item, context); //return array; var countParam = Parameter(typeof(int), "count"); var arrayParam = Parameter(destExpression.Type, "array"); var indexParam = Parameter(typeof(int), "i"); var actions = new List <Expression>(); var parameters = new List <ParameterExpression> { countParam, arrayParam, indexParam }; var countMethod = typeof(Enumerable) .GetTypeInfo() .DeclaredMethods .Single(mi => mi.Name == "Count" && mi.GetParameters().Length == 1) .MakeGenericMethod(sourceElementType); actions.Add(Assign(countParam, Call(countMethod, sourceExpression))); actions.Add(Assign(arrayParam, NewArrayBounds(destElementType, countParam))); actions.Add(Assign(indexParam, Constant(0))); actions.Add(ForEach(sourceExpression, itemParam, Assign(ArrayAccess(arrayParam, PostIncrementAssign(indexParam)), itemExpr) )); actions.Add(arrayParam); var mapExpr = Block(parameters, actions); // return (source == null) ? ifNullExpr : Map<TSourceElement, TDestElement>(source, context); return(Condition(Equal(sourceExpression, Constant(null)), ifNullExpr, mapExpr)); }
private static Expression BuildValueResolverFunc(PropertyMap propertyMap, TypeMapRegistry typeMapRegistry, ParameterExpression srcParam, ParameterExpression destParam, Expression destValueExpr, ParameterExpression ctxtParam) { Expression valueResolverFunc; var valueResolverConfig = propertyMap.ValueResolverConfig; var typeMap = propertyMap.TypeMap; if (valueResolverConfig != null) { Expression ctor; Type resolverType; if (valueResolverConfig.Instance != null) { ctor = Constant(valueResolverConfig.Instance); resolverType = valueResolverConfig.Instance.GetType(); } else { ctor = Call(MakeMemberAccess(ctxtParam, typeof (ResolutionContext).GetDeclaredProperty("Options")), typeof (IMappingOperationOptions).GetDeclaredMethod("CreateInstance") .MakeGenericMethod(valueResolverConfig.Type) ); resolverType = valueResolverConfig.Type; } if (valueResolverConfig.SourceMember != null) { var sourceMember = valueResolverConfig.SourceMember.ReplaceParameters(srcParam); var iResolverType = resolverType.GetTypeInfo() .ImplementedInterfaces.First(t => t.ImplementsGenericInterface(typeof(IMemberValueResolver<,,,>))); var sourceResolverParam = iResolverType.GetGenericArguments()[0]; var destResolverParam = iResolverType.GetGenericArguments()[1]; var sourceMemberResolverParam = iResolverType.GetGenericArguments()[2]; var destMemberResolverParam = iResolverType.GetGenericArguments()[3]; valueResolverFunc = ToType(Call(ToType(ctor, resolverType), resolverType.GetDeclaredMethod("Resolve"), ToType(srcParam, sourceResolverParam), ToType(destParam, destResolverParam), ToType(sourceMember, sourceMemberResolverParam), ToType(destValueExpr, destMemberResolverParam), ctxtParam), propertyMap.DestinationPropertyType); } else if (valueResolverConfig.SourceMemberName != null) { var sourceMember = MakeMemberAccess(srcParam, typeMap.SourceType.GetFieldOrProperty(valueResolverConfig.SourceMemberName)); var iResolverType = resolverType.GetTypeInfo() .ImplementedInterfaces.First(t => t.ImplementsGenericInterface(typeof(IMemberValueResolver<,,,>))); var sourceResolverParam = iResolverType.GetGenericArguments()[0]; var destResolverParam = iResolverType.GetGenericArguments()[1]; var sourceMemberResolverParam = iResolverType.GetGenericArguments()[2]; var destMemberResolverParam = iResolverType.GetGenericArguments()[3]; valueResolverFunc = ToType(Call(ToType(ctor, resolverType), resolverType.GetDeclaredMethod("Resolve"), ToType(srcParam, sourceResolverParam), ToType(destParam, destResolverParam), ToType(sourceMember, sourceMemberResolverParam), ToType(destValueExpr, destMemberResolverParam), ctxtParam), propertyMap.DestinationPropertyType); } else { var iResolverType = resolverType.GetTypeInfo() .ImplementedInterfaces.First(t => t.IsGenericType() && t.GetGenericTypeDefinition() == typeof(IValueResolver<,,>)); var sourceResolverParam = iResolverType.GetGenericArguments()[0]; var destResolverParam = iResolverType.GetGenericArguments()[1]; var destMemberResolverParam = iResolverType.GetGenericArguments()[2]; valueResolverFunc = ToType(Call(ToType(ctor, resolverType), iResolverType.GetDeclaredMethod("Resolve"), ToType(srcParam, sourceResolverParam), ToType(destParam, destResolverParam), ToType(destValueExpr, destMemberResolverParam), ctxtParam), propertyMap.DestinationPropertyType); } } else if (propertyMap.CustomResolver != null) { valueResolverFunc = propertyMap.CustomResolver.ReplaceParameters(srcParam, destParam, destValueExpr, ctxtParam); } else if (propertyMap.CustomExpression != null) { var nullCheckedExpression = propertyMap.CustomExpression.ReplaceParameters(srcParam).IfNotNull(propertyMap.DestinationPropertyType); valueResolverFunc = TryCatch(nullCheckedExpression, Catch(typeof(NullReferenceException), Default(nullCheckedExpression.Type))); } else if (propertyMap.SourceMembers.Any() && propertyMap.SourceType != null ) { var last = propertyMap.SourceMembers.Last(); var pi = last as PropertyInfo; if (pi != null && pi.GetGetMethod(true) == null) { valueResolverFunc = Default(last.GetMemberType()); } else { valueResolverFunc = propertyMap.SourceMembers.Aggregate( (Expression) srcParam, (inner, getter) => getter is MethodInfo ? getter.IsStatic() ? Call(null, (MethodInfo) getter, inner) : (Expression) Call(inner, (MethodInfo) getter) : MakeMemberAccess(getter.IsStatic() ? null : inner, getter) ); valueResolverFunc = valueResolverFunc.IfNotNull(propertyMap.DestinationPropertyType); } } else if (propertyMap.SourceMember != null) { valueResolverFunc = MakeMemberAccess(srcParam, propertyMap.SourceMember); } else { valueResolverFunc = Throw(Constant(new Exception("I done blowed up"))); } if (propertyMap.DestinationPropertyType == typeof (string) && valueResolverFunc.Type != typeof (string) && typeMapRegistry.GetTypeMap(new TypePair(valueResolverFunc.Type, propertyMap.DestinationPropertyType)) == null) { valueResolverFunc = Call(valueResolverFunc, typeof(object).GetDeclaredMethod("ToString", new Type[0])); } if (propertyMap.NullSubstitute != null) { Expression value = Constant(propertyMap.NullSubstitute); if (propertyMap.NullSubstitute.GetType() != propertyMap.DestinationPropertyType) value = ToType(value, propertyMap.DestinationPropertyType); valueResolverFunc = MakeBinary(ExpressionType.Coalesce, valueResolverFunc, value); } else if (!typeMap.Profile.AllowNullDestinationValues) { var toCreate = propertyMap.SourceType ?? propertyMap.DestinationPropertyType; if (!toCreate.GetTypeInfo().IsValueType) { valueResolverFunc = MakeBinary(ExpressionType.Coalesce, valueResolverFunc, ToType(Call( typeof (ObjectCreator).GetDeclaredMethod("CreateNonNullValue"), Constant(toCreate) ), propertyMap.SourceType)); } } return valueResolverFunc; }