public Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider,
         PropertyMap propertyMap, Expression sourceExpression, Expression destExpression,
         Expression contextExpression)
     =>
     typeMapRegistry.MapCollectionExpression(configurationProvider, propertyMap, sourceExpression, destExpression,
         contextExpression, CollectionMapperExtensions.IfNotNull, typeof(Dictionary<,>),
         CollectionMapperExtensions.MapItemExpr);
                public Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider,
                    PropertyMap propertyMap, Expression sourceExpression, Expression destExpression, Expression contextExpression)
                {
                    Expression<Func<DestinationType>> expr = () => new DestinationType();

                    return expr.Body;
                }
        private static Expression CreateDestinationFunc(
            TypeMap typeMap,
            TypeMapRegistry typeMapRegistry,
            ParameterExpression srcParam,
            ParameterExpression destParam,
            ParameterExpression ctxtParam)
        {
            var newDestFunc = ToType(CreateNewDestinationFunc(typeMap, typeMapRegistry, srcParam, ctxtParam),
                typeMap.DestinationTypeToUse);

            var getDest = typeMap.DestinationTypeToUse.GetTypeInfo().IsValueType
                ? newDestFunc
                : Coalesce(destParam, newDestFunc);

            Expression destinationFunc = Assign(destParam, getDest);

            if (typeMap.PreserveReferences)
            {
                var dest = Variable(typeof (object), "dest");

                Expression valueBag = Property(ctxtParam, "InstanceCache");
                var set = Assign(Property(valueBag, "Item", srcParam), dest);
                var setCache =
                    IfThen(NotEqual(srcParam, Constant(null)), set);

                destinationFunc = Block(new[] {dest}, Assign(dest, destinationFunc), setCache, dest);
            }
            return destinationFunc;
        }
        public Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider, PropertyMap propertyMap, Expression sourceExpression, Expression destExpression, Expression contextExpression)
        {
            var listType = typeof(List<>).MakeGenericType(TypeHelper.GetElementType(destExpression.Type));
            var list = typeMapRegistry.MapCollectionExpression(configurationProvider, propertyMap, sourceExpression, Default(listType), contextExpression, _ => Constant(false), typeof(List<>), CollectionMapperExtensions.MapItemExpr);
            var dest = Variable(listType, "dest");

            return Block(new[] { dest }, Assign(dest, list), Condition(NotEqual(dest, Default(listType)), New(destExpression.Type.GetConstructors().First(), dest), Default(destExpression.Type)));
        }
Exemple #5
0
 public Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider,
     PropertyMap propertyMap, Expression sourceExpression, Expression destExpression,
     Expression contextExpression)
 {
     return Condition(Equal(sourceExpression, Default(sourceExpression.Type)),
         Constant(null, typeof(string)),
         Call(sourceExpression, typeof(object).GetDeclaredMethod("ToString")));
 }
        public Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider,
            PropertyMap propertyMap, Expression sourceExpression, Expression destExpression,
            Expression contextExpression)
        {
            var listType = typeof(List<>).MakeGenericType(TypeHelper.GetElementType(destExpression.Type));

            return typeMapRegistry.MapCollectionExpression(configurationProvider, propertyMap, sourceExpression,
                Expression.Default(listType), contextExpression, IfEditableList, typeof(List<>),
                CollectionMapperExtensions.MapItemExpr);
        }
 public TypeMapPlanBuilder(IConfigurationProvider configurationProvider, TypeMapRegistry typeMapRegistry, TypeMap typeMap)
 {
     _configurationProvider = configurationProvider;
     _typeMapRegistry = typeMapRegistry;
     _typeMap = typeMap;
     _source = Parameter(typeMap.SourceType, "src");
     _initialDestination = Parameter(typeMap.DestinationTypeToUse, "dest");
     _context = Parameter(typeof(ResolutionContext), "ctxt");
     _destination = Variable(_initialDestination.Type, "typeMapDestination");
 }
 public Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider,
     PropertyMap propertyMap, Expression sourceExpression, Expression destExpression,
     Expression contextExpression)
 {
     var toStringCall = Call(sourceExpression, typeof(object).GetDeclaredMethod("ToString"));
     if(sourceExpression.Type.IsValueType())
     {
         return toStringCall;
     }
     return Condition(Equal(sourceExpression, Constant(null)), Constant(null, typeof(string)), toStringCall);
 }
        public Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider, PropertyMap propertyMap, Expression sourceExpression, Expression destExpression, Expression contextExpression)
        {
            Type destElementType = TypeHelper.GetElementType(destExpression.Type);

            Expression<Action> expr = () => Array.Copy(null, null, 0);
            var copyMethod = ((MethodCallExpression) expr.Body).Method;

            var valueIfNullExpr = configurationProvider.Configuration.AllowNullCollections
                ? (Expression) Constant(null, destExpression.Type)
                : NewArrayBounds(destElementType, Constant(0));

            var dest = Parameter(destExpression.Type, "destArray");
            var sourceLength = Parameter(typeof(int), "sourceLength");
            var lengthProperty = typeof(Array).GetDeclaredProperty("Length");
            var mapExpr = Block(
                new[] {dest, sourceLength},
                Assign(sourceLength, Property(sourceExpression, lengthProperty)),
                Assign(dest, NewArrayBounds(destElementType, sourceLength)),
                Call(copyMethod, sourceExpression, dest, sourceLength),
                dest
            );

            return Condition(Equal(sourceExpression, Constant(null)), valueIfNullExpr, mapExpr);
        }
        private static Expression CreatePropertyMapFunc(
            PropertyMap propertyMap,
            IConfigurationProvider configurationProvider,
            TypeMapRegistry typeMapRegistry,
            ParameterExpression srcParam,
            ParameterExpression destParam,
            ParameterExpression 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.DestinationPropertyType);

            var valueResolverExpr = BuildValueResolverFunc(propertyMap, typeMapRegistry, srcParam, getter, ctxtParam);

            if (propertyMap.SourceType != null && propertyMap.DestinationPropertyType != null)
            {
                var typePair = new TypePair(propertyMap.SourceType, propertyMap.DestinationPropertyType);
                var typeMap  = configurationProvider.ResolveTypeMap(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;
                    if (expressionMapper != null)
                    {
                        valueResolverExpr = expressionMapper.MapExpression(typeMapRegistry, configurationProvider, propertyMap, valueResolverExpr, destValueExpr,
                                                                           ctxtParam);
                    }
                    else
                    {
                        valueResolverExpr = SetMap(propertyMap, valueResolverExpr, destValueExpr, ctxtParam);
                    }
                }
            }
            else
            {
                valueResolverExpr = SetMap(propertyMap, valueResolverExpr, destValueExpr, ctxtParam);
            }

            if (propertyMap.Condition != null)
            {
                valueResolverExpr =
                    Condition(
                        propertyMap.Condition.ConvertReplaceParameters(
                            srcParam,
                            destParam,
                            ToType(valueResolverExpr, propertyMap.Condition.Parameters[2].Type),
                            ToType(getter, propertyMap.Condition.Parameters[2].Type),
                            ctxtParam
                            ),
                        ToType(valueResolverExpr, propertyMap.DestinationPropertyType),
                        getter
                        );
            }

            Expression mapperExpr;

            if (propertyMap.DestinationProperty.MemberInfo is FieldInfo)
            {
                mapperExpr = propertyMap.SourceType != propertyMap.DestinationPropertyType
                    ? Assign(destMember, ToType(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
                        ? ToType(valueResolverExpr, propertyMap.DestinationPropertyType)
                        : valueResolverExpr);
                }
            }

            if (propertyMap.PreCondition != null)
            {
                mapperExpr = IfThen(
                    propertyMap.PreCondition.ConvertReplaceParameters(srcParam, ctxtParam),
                    mapperExpr
                    );
            }

            return(mapperExpr);
        }
        private static Expression CreateNewDestinationFunc(
            TypeMap typeMap,
            TypeMapRegistry typeMapRegistry,
            ParameterExpression srcParam,
            ParameterExpression ctxtParam)
        {
            if (typeMap.DestinationCtor != null)
                return typeMap.DestinationCtor.ReplaceParameters(srcParam, ctxtParam);

            if (typeMap.ConstructDestinationUsingServiceLocator)
                return Call(MakeMemberAccess(ctxtParam, typeof (ResolutionContext).GetProperty("Options")),
                    typeof (MappingOperationOptions).GetMethod("CreateInstance")
                        .MakeGenericMethod(typeMap.DestinationTypeToUse)
                    );

            if (typeMap.ConstructorMap?.CanResolve == true)
                return typeMap.ConstructorMap.BuildExpression(typeMapRegistry, srcParam, ctxtParam);

#if NET45
            if (typeMap.DestinationTypeToUse.IsInterface())
            {
                var ctor = Call(Constant(ObjectCreator.DelegateFactory), typeof(DelegateFactory).GetMethod("CreateCtor", new[] { typeof(Type) }), Call(New(typeof(ProxyGenerator)), typeof(ProxyGenerator).GetMethod("GetProxyType"), Constant(typeMap.DestinationTypeToUse)));
                // We're invoking a delegate here
                return Invoke(ctor);
            }
#endif

            if (typeMap.DestinationTypeToUse.IsAbstract())
                return Constant(null);

            if (typeMap.DestinationTypeToUse.IsGenericTypeDefinition())
                return Constant(null);

            return DelegateFactory.GenerateConstructorExpression(typeMap.DestinationTypeToUse);
        }
        private static Expression CreateAssignmentFunc(
            TypeMap typeMap,
            IConfigurationProvider configurationProvider,
            TypeMapRegistry registry,
            ParameterExpression srcParam,
            ParameterExpression destParam,
            ParameterExpression ctxtParam,
            Expression destinationFunc,
            ParameterExpression destination,
            bool constructorMapping)
        {
            var actions = new List<Expression>();
            foreach(var propertyMap in typeMap.GetPropertyMaps())
            {
                if(!propertyMap.CanResolveValue())
                {
                    continue;
                }
                var property = TryPropertyMap(propertyMap, configurationProvider, registry, srcParam, destination, ctxtParam);
                if(constructorMapping && typeMap.ConstructorParameterMatches(propertyMap.DestinationProperty.Name))
                {
                    property = IfThen(NotEqual(destParam, Expression.Constant(null)), property);
                }
                actions.Add(property);
            }
            foreach (var beforeMapAction in typeMap.BeforeMapActions)
            {
                actions.Insert(0, beforeMapAction.ReplaceParameters(srcParam, destination, ctxtParam));
            }
            actions.Insert(0, destinationFunc);
            if (typeMap.MaxDepth > 0)
            {
                actions.Insert(0, Call(ctxtParam, ((MethodCallExpression)IncTypeDepthInfo.Body).Method, Constant(typeMap.Types)));
            }
            actions.AddRange(
                typeMap.AfterMapActions.Select(
                    afterMapAction => afterMapAction.ReplaceParameters(srcParam, destination, ctxtParam)));

            if (typeMap.MaxDepth > 0)
            {
                actions.Add(Call(ctxtParam, ((MethodCallExpression)DecTypeDepthInfo.Body).Method, Constant(typeMap.Types)));
            }

            actions.Add(destination);

            return Block(actions);
        }
 public Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider, PropertyMap propertyMap, Expression sourceExpression, Expression destExpression, Expression contextExpression)
 {
     var implicitOperator = GetImplicitConversionOperator(new TypePair(sourceExpression.Type, destExpression.Type));
     return Expression.Call(null, implicitOperator, sourceExpression);
 }
        public Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider, PropertyMap propertyMap, Expression sourceExpression, Expression destExpression, Expression contextExpression)
        {
            var implicitOperator = GetImplicitConversionOperator(new TypePair(sourceExpression.Type, destExpression.Type));

            return(Expression.Call(null, implicitOperator, sourceExpression));
        }
 public Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider, PropertyMap propertyMap, Expression sourceExpression, Expression destExpression, Expression contextExpression)
 {
     return(Expression.Call(null, MapMethodInfo.MakeGenericMethod(Nullable.GetUnderlyingType(sourceExpression.Type), destExpression.Type), sourceExpression, destExpression, contextExpression));
 }
 public Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider, Expression sourceExpression, Expression destExpression, Expression contextExpression)
 {
     return(Expression.Condition(Expression.Equal(sourceExpression, Expression.Default(sourceExpression.Type)),
                                 Expression.Constant(null, typeof(string)),
                                 Expression.Call(sourceExpression, typeof(object).GetMethod("ToString"))));
 }
        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;
        }
Exemple #18
0
 public Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider, Expression sourceExpression, Expression destExpression, Expression contextExpression)
 {
     return(Expression.Call(null,
                            MapMethodInfo.MakeGenericMethod(TypeHelper.GetElementType(sourceExpression.Type), TypeHelper.GetElementType(destExpression.Type)),
                            sourceExpression, destExpression, contextExpression));
 }
 public Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider, PropertyMap propertyMap, Expression sourceExpression, Expression destExpression, Expression contextExpression)
 {
     return Expression.Call(null, MapMethodInfo, sourceExpression);
 }
Exemple #20
0
 public Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider, PropertyMap propertyMap, Expression sourceExpression, Expression destExpression, Expression contextExpression)
 => typeMapRegistry.MapCollectionExpression(configurationProvider, propertyMap, sourceExpression, destExpression, contextExpression, CollectionMapperExtensions.IfNotNull, typeof(List <>), CollectionMapperExtensions.MapItemExpr);
Exemple #21
0
        internal static Expression MapCollectionExpression(this TypeMapRegistry typeMapRegistry,
                                                           IConfigurationProvider configurationProvider, PropertyMap propertyMap, Expression sourceExpression,
                                                           Expression destExpression, Expression contextExpression, Func <Expression, Expression> conditionalExpression, Type ifInterfaceType, MapItem mapItem)
        {
            var newExpr   = destExpression.NewIfConditionFails(conditionalExpression, ifInterfaceType);
            var itemParam = Parameter(TypeHelper.GetElementType(sourceExpression.Type), "item");
            var itemExpr  = mapItem(typeMapRegistry, configurationProvider, propertyMap, sourceExpression.Type, destExpression.Type, itemParam, contextExpression);

            var blockExprs  = new List <Expression>();
            var blockParams = new List <ParameterExpression>();
            var dest        = destExpression;

            if (destExpression.Type.IsCollectionType())
            {
                if (propertyMap == null)
                {
                    var destParam = Parameter(newExpr.Type, "d");
                    blockParams.Add(destParam);

                    blockExprs.Add(Assign(destParam, destExpression));

                    dest = destParam;

                    var clearMethod = typeof(ICollection <>).MakeGenericType(TypeHelper.GetElementType(destExpression.Type)).GetMethod("Clear");
                    blockExprs.Add(IfThenElse(NotEqual(destExpression, Constant(null)),
                                              Call(destExpression, clearMethod),
                                              Assign(destParam, newExpr)
                                              ));
                }
                else if (propertyMap.UseDestinationValue)
                {
                    var clearMethod = typeof(ICollection <>).MakeGenericType(TypeHelper.GetElementType(destExpression.Type)).GetMethod("Clear");
                    blockExprs.Add(Call(destExpression, clearMethod));
                }
                else
                {
                    var destParam = Parameter(newExpr.Type, "d");
                    blockParams.Add(destParam);
                    blockExprs.Add(Assign(destParam, newExpr));
                    dest = destParam;
                }
            }
            else
            {
                var destParam = Parameter(newExpr.Type, "d");
                blockParams.Add(destParam);
                blockExprs.Add(Assign(destParam, newExpr));
                dest = destParam;
            }

            var cast = typeof(Enumerable).GetTypeInfo().DeclaredMethods.First(_ => _.Name == "Cast").MakeGenericMethod(itemParam.Type);

            var addMethod = typeof(ICollection <>).MakeGenericType(TypeHelper.GetElementType(destExpression.Type)).GetMethod("Add");

            if (!sourceExpression.Type.GetTypeInfo().IsGenericType)
            {
                sourceExpression = Call(null, cast, sourceExpression);
            }
            blockExprs.Add(ForEach(sourceExpression, itemParam, Call(
                                       dest,
                                       addMethod,
                                       itemExpr)));

            blockExprs.Add(dest);

            var mapExpr = Block(blockParams, blockExprs);

            var ifNullExpr = configurationProvider.AllowNullCollections
                     ? Constant(null, destExpression.Type)
                     : newExpr;

            return(Condition(
                       Equal(sourceExpression, Constant(null)),
                       ToType(ifNullExpr, destExpression.Type),
                       ToType(mapExpr, destExpression.Type)));
        }
        internal static Expression MapCollectionExpression(this TypeMapRegistry typeMapRegistry,
                                                           IConfigurationProvider configurationProvider, PropertyMap propertyMap, Expression sourceExpression,
                                                           Expression destExpression, Expression contextExpression, Func <Expression, Expression> conditionalExpression, Type ifInterfaceType, MapItem mapItem)
        {
            var passedDestination  = Variable(destExpression.Type, "passedDestination");
            var newExpressionValue = passedDestination.NewIfConditionFails(conditionalExpression, ifInterfaceType);
            var newExpression      = Variable(newExpressionValue.Type, "collectionDestination");
            var sourceElementType  = TypeHelper.GetElementType(sourceExpression.Type);
            var itemParam          = Parameter(sourceElementType, "item");
            var itemExpr           = mapItem(typeMapRegistry, configurationProvider, propertyMap, sourceExpression.Type, passedDestination.Type, itemParam, contextExpression);

            var blockExpressions = new List <Expression>();
            var blockVariables   = new List <ParameterExpression> {
                newExpression, passedDestination
            };
            Expression destination;
            var        destinationElementType    = itemExpr.Type;
            var        destinationCollectionType = typeof(ICollection <>).MakeGenericType(destinationElementType);
            var        clearMethod = destinationCollectionType.GetDeclaredMethod("Clear");

            if (passedDestination.Type.IsCollectionType())
            {
                if (propertyMap == null)
                {
                    destination = newExpression;
                    blockExpressions.Add(IfThenElse(NotEqual(passedDestination, Constant(null)),
                                                    Call(passedDestination, clearMethod),
                                                    Assign(destination, newExpression)
                                                    ));
                }
                else if (propertyMap.UseDestinationValue)
                {
                    destination = passedDestination;
                    blockExpressions.Add(Call(passedDestination, clearMethod));
                }
                else
                {
                    destination = newExpression;
                }
            }
            else
            {
                destination = newExpression;
            }

            var cast = typeof(Enumerable).GetTypeInfo().DeclaredMethods.First(_ => _.Name == "Cast").MakeGenericMethod(itemParam.Type);

            var addMethod     = destinationCollectionType.GetDeclaredMethod("Add");
            var genericSource = sourceExpression.Type.GetTypeInfo().IsGenericType ? sourceExpression : Call(null, cast, sourceExpression);

            blockExpressions.Add(ForEach(genericSource, itemParam, Call(
                                             destination,
                                             addMethod,
                                             itemExpr)));

            blockExpressions.Add(destination);

            var mapExpr = Block(blockExpressions);

            var ifNullExpr = configurationProvider.Configuration.AllowNullCollections ? Constant(null, passedDestination.Type) : (Expression)newExpression;
            var checkNull  = Block(blockVariables,
                                   Assign(passedDestination, destExpression),
                                   Assign(newExpression, newExpressionValue),
                                   Condition(Equal(sourceExpression, Constant(null)), ToType(ifNullExpr, passedDestination.Type), ToType(mapExpr, passedDestination.Type))
                                   );

            if (propertyMap != null)
            {
                return(checkNull);
            }
            var elementTypeMap = configurationProvider.ResolveTypeMap(sourceElementType, destinationElementType);

            if (elementTypeMap == null)
            {
                return(checkNull);
            }
            var checkContext = TypeMapPlanBuilder.CheckContext(elementTypeMap, contextExpression);

            if (checkContext == null)
            {
                return(checkNull);
            }
            return(Block(checkContext, checkNull));
        }
        private static Expression TryPropertyMap(
            PropertyMap pm,
            IConfigurationProvider configurationProvider,
            TypeMapRegistry registry,
            ParameterExpression srcParam,
            ParameterExpression destParam,
            ParameterExpression ctxtParam)
        {
            var pmExpression = CreatePropertyMapFunc(pm, configurationProvider, registry, srcParam, destParam, ctxtParam);

            if (pmExpression == null)
                return null;

            var exception = Parameter(typeof (Exception), "ex");

            var mappingExceptionCtor = ((NewExpression)CtorExpression.Body).Constructor;

            return TryCatch(Block(typeof (void), pmExpression),
                MakeCatchBlock(typeof (Exception), exception,
                    Throw(New(mappingExceptionCtor, Constant("Error mapping types."), exception, Constant(pm.TypeMap.Types), Constant(pm.TypeMap), Constant(pm))), null));
        }
        private static Expression BuildValueResolverFunc(PropertyMap propertyMap, TypeMapRegistry typeMapRegistry,
                                                         ParameterExpression srcParam,
                                                         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).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;
                }

                var iResolverType =
                    resolverType.GetTypeInfo()
                    .ImplementedInterfaces.First(t => t.ImplementsGenericInterface(typeof(IValueResolver <,>)));

                var sourceResolverParam = iResolverType.GetGenericArguments()[0];
                var destResolverParam   = iResolverType.GetGenericArguments()[1];

                valueResolverFunc =
                    ToType(Call(ToType(ctor, resolverType), resolverType.GetMethod("Resolve"),
                                ToType(sourceFunc, sourceResolverParam),
                                ToType(destValueExpr, destResolverParam),
                                ctxtParam),
                           propertyMap.DestinationPropertyType);
            }
            else if (propertyMap.CustomResolver != null)
            {
                valueResolverFunc = propertyMap.CustomResolver.ReplaceParameters(srcParam, destValueExpr, 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 = 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).GetMethod("CreateNonNullValue"),
                                                              Constant(toCreate)
                                                              ), propertyMap.SourceType));
                }
            }

            return(valueResolverFunc);
        }
 private static Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider,
     PropertyMap propertyMap, Expression itemParam, Expression contextParam, TypePair typePair)
 {
     Expression itemExpr;
     var typeMap = configurationProvider.ResolveTypeMap(typePair);
     if (typeMap != null && (typeMap.TypeConverterType != null || typeMap.CustomMapper != null))
     {
         if (!typeMap.Sealed)
             typeMap.Seal(typeMapRegistry, configurationProvider);
         return typeMap.MapExpression.ReplaceParameters(itemParam, Default(typePair.DestinationType), contextParam);
     }
     var match = configurationProvider.GetMappers().FirstOrDefault(m => m.IsMatch(typePair));
     if (match != null && typeMap == null)
     {
         itemExpr =
             ToType(
                 match.MapExpression(typeMapRegistry, configurationProvider, propertyMap, itemParam,
                     Default(typePair.DestinationType), contextParam), typePair.DestinationType);
     }
     else
     {
         var mapMethod =
             typeof (ResolutionContext).GetDeclaredMethods()
                 .First(m => m.Name == "Map")
                 .MakeGenericMethod(typePair.SourceType, typePair.DestinationType);
         itemExpr = Call(contextParam, mapMethod, itemParam, Default(typePair.DestinationType));
     }
     return itemExpr;
 }
        private static Expression CreatePropertyMapFunc(
            PropertyMap propertyMap,
            IConfigurationProvider configurationProvider,
            TypeMapRegistry typeMapRegistry,
            ParameterExpression srcParam,
            ParameterExpression destParam,
            ParameterExpression ctxtParam)
        {
            var destMember = MakeMemberAccess(destParam, propertyMap.DestinationProperty);

            Expression getter;

            var pi = propertyMap.DestinationProperty as PropertyInfo;
            if (pi != null && pi.GetGetMethod(true) == null)
            {
                getter = Default(propertyMap.DestinationPropertyType);
            }
            else
            {
                getter = destMember;
            }

            var destValueExpr = propertyMap.UseDestinationValue
                ? getter
                : Default(propertyMap.DestinationPropertyType);

            var valueResolverExpr = BuildValueResolverFunc(propertyMap, typeMapRegistry, srcParam, destParam, getter, ctxtParam);

            if (propertyMap.DestinationPropertyType != null)
            {
                var typePair = new TypePair(valueResolverExpr.Type, propertyMap.DestinationPropertyType);
                var typeMap = configurationProvider.ResolveTypeMap(typePair);
                var match = configurationProvider.GetMappers().FirstOrDefault(m => m.IsMatch(typePair));
                if (typeMap != null && (typeMap.TypeConverterType != null || typeMap.CustomMapper != null))
                {
                    if(typeMap.Sealed != true)
                        typeMap.Seal(typeMapRegistry, configurationProvider);
                    valueResolverExpr = typeMap.MapExpression.ConvertReplaceParameters(valueResolverExpr, destValueExpr, ctxtParam);
                }
                else if (match != null && typeMap == null)
                {
                    valueResolverExpr = match.MapExpression(typeMapRegistry, configurationProvider,
                        propertyMap, valueResolverExpr, destValueExpr,
                        ctxtParam);
                }
                else
                {
                    valueResolverExpr = SetMap(propertyMap, valueResolverExpr, destValueExpr, ctxtParam);
                }
            }
            else
            {
                valueResolverExpr = SetMap(propertyMap, valueResolverExpr, destValueExpr, ctxtParam);
            }

            Expression mapperExpr;
            if (propertyMap.DestinationProperty is FieldInfo)
            {
                mapperExpr = propertyMap.SourceType != propertyMap.DestinationPropertyType
                    ? Assign(destMember, ToType(valueResolverExpr, propertyMap.DestinationPropertyType))
                    : Assign(getter, valueResolverExpr);
            }
            else
            {
                var setter = ((PropertyInfo) propertyMap.DestinationProperty).GetSetMethod(true);
                if (setter == null)
                {
                    mapperExpr = valueResolverExpr;
                }
                else
                {
                    mapperExpr = Assign(destMember, propertyMap.SourceType != propertyMap.DestinationPropertyType
                        ? ToType(valueResolverExpr, propertyMap.DestinationPropertyType)
                        : valueResolverExpr);
                }
            }

            if (propertyMap.PreCondition != null)
            {
                mapperExpr = IfThen(
                    propertyMap.PreCondition.ConvertReplaceParameters(srcParam, ctxtParam),
                    mapperExpr
                    );
            }
            if (propertyMap.Condition != null)
            {
                mapperExpr = IfThen(
                    propertyMap.Condition.ConvertReplaceParameters(
                        srcParam,
                        destParam,
                        ToType(valueResolverExpr, propertyMap.Condition.Parameters[2].Type),
                        ToType(getter, propertyMap.Condition.Parameters[2].Type),
                        ctxtParam
                        ),
                    mapperExpr
                    );
            }

            return mapperExpr;
        }
        private static Expression CreateAssignmentFunc(
            TypeMap typeMap,
            IConfigurationProvider configurationProvider,
            TypeMapRegistry registry,
            ParameterExpression srcParam,
            ParameterExpression destParam,
            ParameterExpression ctxtParam,
            Expression destinationFunc,
            ref ParameterExpression contextToReuse)
        {
            var assignTypeMap = Assign(MakeMemberAccess(ctxtParam, typeof (ResolutionContext).GetProperty("TypeMap")),
                Constant(typeMap));

            var beforeMap = Call(ctxtParam, typeof (ResolutionContext).GetMethod("BeforeMap"), ToObject(destParam));


            ParameterExpression propertyContext = contextToReuse;
            var typeMaps = typeMap.GetPropertyMaps()
                    .Where(pm => pm.CanResolveValue())
                    .Select(pm => TryPropertyMap(pm, configurationProvider, registry, srcParam, destParam, ctxtParam, ref propertyContext))
                    .ToList();
            contextToReuse = propertyContext;
            var afterMap = Call(ctxtParam, typeof (ResolutionContext).GetMethod("AfterMap"), ToObject(destParam));

            var actions = typeMaps;

            foreach (var beforeMapAction in typeMap.BeforeMapActions)
            {
                actions.Insert(0, beforeMapAction.ReplaceParameters(srcParam, destParam, ctxtParam));
            }
            actions.Insert(0, beforeMap);
            actions.Insert(0, destinationFunc);
            actions.Insert(0, assignTypeMap);
            ParameterExpression[] variables;
            if(propertyContext != null)
            {
                var createPropertyContext = CreatePropertyContext(propertyContext, ctxtParam);
                actions.Insert(0, createPropertyContext);
                variables = new[] { propertyContext };
            }
            else
            {
                variables = new ParameterExpression[0];
            }

            actions.Add(afterMap);

            actions.AddRange(
                typeMap.AfterMapActions.Select(
                    afterMapAction => afterMapAction.ReplaceParameters(srcParam, destParam, ctxtParam)));

            actions.Add(destParam);

            return Block(variables, actions);
        }
        private static Expression CreateNewDestinationFunc(
            TypeMap typeMap,
            TypeMapRegistry typeMapRegistry,
            ParameterExpression srcParam,
            ParameterExpression ctxtParam,
            ref ParameterExpression contextToReuse)
        {
            if (typeMap.DestinationCtor != null)
                return typeMap.DestinationCtor.ReplaceParameters(srcParam, ctxtParam);

            if (typeMap.ConstructDestinationUsingServiceLocator)
                return Call(MakeMemberAccess(ctxtParam, typeof (ResolutionContext).GetProperty("Options")),
                    typeof (MappingOperationOptions).GetMethod("CreateInstance")
                        .MakeGenericMethod(typeMap.DestinationType)
                    );

            if (typeMap.ConstructorMap?.CanResolve == true)
                return typeMap.ConstructorMap.BuildExpression(typeMapRegistry, srcParam, ctxtParam, ref contextToReuse);

            if (typeMap.DestinationType.IsInterface())
            {
#if PORTABLE
                Block(typeof (object),
                    Throw(
                        Constant(
                            new PlatformNotSupportedException("Mapping to interfaces through proxies not supported."))),
                    Constant(null));
#else
                var ctor = Call(Constant(ObjectCreator.DelegateFactory), typeof(DelegateFactory).GetMethod("CreateCtor", new[] { typeof(Type) }), Call(New(typeof(ProxyGenerator)), typeof(ProxyGenerator).GetMethod("GetProxyType"), Constant(typeMap.DestinationType)));
                return Invoke(ctor);
#endif
            }

            if (typeMap.DestinationType.IsAbstract())
                return Constant(null);

            if (typeMap.DestinationType.IsGenericTypeDefinition())
                return Constant(null);

            return DelegateFactory.GenerateConstructorExpression(typeMap.DestinationType);
        }
Exemple #29
0
 public Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider, PropertyMap propertyMap, Expression sourceExpression, Expression destExpression, Expression contextExpression)
 {
     return(Expression.Call(null, MapMethodInfo, sourceExpression));
 }
        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;
        }
Exemple #31
0
 public Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider, PropertyMap propertyMap, Expression sourceExpression, Expression destExpression, Expression contextExpression)
 {
     return(Expression.Call(null, MapMethodInfo.MakeGenericMethod(sourceExpression.Type, destExpression.Type), sourceExpression, destExpression, contextExpression, Expression.Constant(CollectionMapperExtensions.Constructor(destExpression.Type))));
 }
        public Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider, PropertyMap propertyMap, Expression sourceExpression, Expression destExpression, Expression contextExpression)
        {
            var typeMap = new TypePair(sourceExpression.Type, destExpression.Type);

            return(_converters[typeMap].Value.ReplaceParameters(sourceExpression));
        }
Exemple #33
0
 public Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider, PropertyMap propertyMap, Expression sourceExpression, Expression destExpression, Expression contextExpression)
 {
     var typeMap = new TypePair(sourceExpression.Type, destExpression.Type);
     return _converters[typeMap].ReplaceParameters(sourceExpression);
 }
        public static LambdaExpression BuildMapperFunc(TypeMap typeMap, IConfigurationProvider configurationProvider, TypeMapRegistry typeMapRegistry)
        {
            if (typeMap.SourceType.IsGenericTypeDefinition() || typeMap.DestinationTypeToUse.IsGenericTypeDefinition())
            {
                return(null);
            }

            var srcParam  = Parameter(typeMap.SourceType, "src");
            var destParam = Parameter(typeMap.DestinationTypeToUse, "dest");
            var ctxtParam = Parameter(typeof(ResolutionContext), "ctxt");

            if (typeMap.Substitution != null)
            {
                return(Lambda(typeMap.Substitution.ReplaceParameters(srcParam, destParam, ctxtParam), srcParam,
                              destParam, ctxtParam));
            }

            if (typeMap.TypeConverterType != null)
            {
                Type type;
                if (typeMap.TypeConverterType.IsGenericTypeDefinition())
                {
                    var genericTypeParam = typeMap.SourceType.IsGenericType()
                        ? typeMap.SourceType.GetTypeInfo().GenericTypeArguments[0]
                        : typeMap.DestinationTypeToUse.GetTypeInfo().GenericTypeArguments[0];
                    type = typeMap.TypeConverterType.MakeGenericType(genericTypeParam);
                }
                else
                {
                    type = typeMap.TypeConverterType;
                }

                // (src, dest, ctxt) => ((ITypeConverter<TSource, TDest>)ctxt.Options.CreateInstance<TypeConverterType>()).ToType(src, ctxt);
                var converterInterfaceType = typeof(ITypeConverter <,>).MakeGenericType(typeMap.SourceType,
                                                                                        typeMap.DestinationTypeToUse);
                return(Lambda(
                           Call(
                               ToType(
                                   Call(
                                       MakeMemberAccess(ctxtParam, typeof(ResolutionContext).GetProperty("Options")),
                                       typeof(MappingOperationOptions).GetMethod("CreateInstance")
                                       .MakeGenericMethod(type)
                                       ),
                                   converterInterfaceType),
                               converterInterfaceType.GetMethod("Convert"),
                               srcParam, ctxtParam
                               ),
                           srcParam, destParam, ctxtParam));
            }

            if (typeMap.CustomMapper != null)
            {
                return(Lambda(typeMap.CustomMapper.ReplaceParameters(srcParam, destParam, ctxtParam), srcParam,
                              destParam, ctxtParam));
            }

            if (typeMap.CustomProjection != null)
            {
                return(Lambda(typeMap.CustomProjection.ReplaceParameters(srcParam), srcParam, destParam, ctxtParam));
            }

            var destinationFunc = CreateDestinationFunc(typeMap, typeMapRegistry, srcParam, destParam, ctxtParam);

            var assignmentFunc = CreateAssignmentFunc(typeMap, configurationProvider, typeMapRegistry, srcParam, destParam, ctxtParam, destinationFunc);

            var mapperFunc = CreateMapperFunc(typeMap, srcParam, destParam, ctxtParam, assignmentFunc);

            var lambdaExpr = Lambda(mapperFunc, srcParam, destParam, ctxtParam);

            return(lambdaExpr);
        }
 public static Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider,
     TypePair typePair, Expression sourceParameter, Expression contextParameter, PropertyMap propertyMap = null, Expression destinationParameter = null)
 {
     if(destinationParameter == null)
     {
         destinationParameter = Default(typePair.DestinationType);
     }
     var typeMap = configurationProvider.ResolveTypeMap(typePair);
     if(typeMap != null)
     {
         if(!typeMap.HasDerivedTypesToInclude())
         {
             typeMap.Seal(typeMapRegistry, configurationProvider);
             if(typeMap.MapExpression != null)
             {
                 return typeMap.MapExpression.ConvertReplaceParameters(sourceParameter, destinationParameter, contextParameter);
             }
             else
             {
                 return ContextMap(typePair, sourceParameter, contextParameter, destinationParameter);
             }
         }
         else
         {
             return ContextMap(typePair, sourceParameter, contextParameter, destinationParameter);
         }
     }
     var match = configurationProvider.GetMappers().FirstOrDefault(m => m.IsMatch(typePair));
     if(match != null)
     {
         var mapperExpression = match.MapExpression(typeMapRegistry, configurationProvider, propertyMap, sourceParameter, destinationParameter, contextParameter);
         return ToType(mapperExpression, typePair.DestinationType);
     }
     return ContextMap(typePair, sourceParameter, contextParameter, destinationParameter);
 }
        private static Expression CreateAssignmentFunc(
            TypeMap typeMap,
            IConfigurationProvider configurationProvider,
            TypeMapRegistry registry,
            ParameterExpression srcParam,
            ParameterExpression destParam,
            ParameterExpression ctxtParam,
            Expression destinationFunc)
        {
            var typeMaps = typeMap.GetPropertyMaps()
                    .Where(pm => pm.CanResolveValue() && !typeMap.IsMappedThroughConstructor(pm.DestinationProperty.Name))
                    .Select(pm => TryPropertyMap(pm, configurationProvider, registry, srcParam, destParam, ctxtParam))
                    .ToList();

            var actions = typeMaps;

            foreach (var beforeMapAction in typeMap.BeforeMapActions)
            {
                actions.Insert(0, beforeMapAction.ReplaceParameters(srcParam, destParam, ctxtParam));
            }
            actions.Insert(0, destinationFunc);
            if (typeMap.MaxDepth > 0)
            {
                actions.Insert(0, Call(ctxtParam, ((MethodCallExpression)IncTypeDepthInfo.Body).Method, Constant(typeMap.Types)));
            }
            actions.AddRange(
                typeMap.AfterMapActions.Select(
                    afterMapAction => afterMapAction.ReplaceParameters(srcParam, destParam, ctxtParam)));

            if (typeMap.MaxDepth > 0)
            {
                actions.Add(Call(ctxtParam, ((MethodCallExpression)DecTypeDepthInfo.Body).Method, Constant(typeMap.Types)));
            }

            actions.Add(destParam);

            return Block(actions);
        }
        public static LambdaExpression BuildMapperFunc(TypeMap typeMap, IConfigurationProvider configurationProvider, TypeMapRegistry typeMapRegistry)
        {
            if (typeMap.SourceType.IsGenericTypeDefinition() || typeMap.DestinationType.IsGenericTypeDefinition())
                return null;

            var srcParam = Parameter(typeMap.SourceType, "src");
            var destParam = Parameter(typeMap.DestinationType, "dest");
            var ctxtParam = Parameter(typeof (ResolutionContext), "ctxt");

            if (typeMap.Substitution != null)
            {
                return Lambda(typeMap.Substitution.ReplaceParameters(srcParam, destParam, ctxtParam), srcParam,
                    destParam, ctxtParam);
            }

            if (typeMap.TypeConverterType != null)
            {
                Type type;
                if (typeMap.TypeConverterType.IsGenericTypeDefinition())
                {
                    var genericTypeParam = typeMap.SourceType.IsGenericType()
                        ? typeMap.SourceType.GetTypeInfo().GenericTypeArguments[0]
                        : typeMap.DestinationType.GetTypeInfo().GenericTypeArguments[0];
                    type = typeMap.TypeConverterType.MakeGenericType(genericTypeParam);
                }
                else type = typeMap.TypeConverterType;

                // (src, dest, ctxt) => ((ITypeConverter<TSource, TDest>)ctxt.Options.CreateInstance<TypeConverterType>()).Convert(src, ctxt);
                var converterInterfaceType = typeof (ITypeConverter<,>).MakeGenericType(typeMap.SourceType,
                    typeMap.DestinationType);
                return Lambda(
                    Call(
                        Convert(
                            Call(
                                MakeMemberAccess(ctxtParam, typeof (ResolutionContext).GetProperty("Options")),
                                typeof (MappingOperationOptions).GetMethod("CreateInstance")
                                    .MakeGenericMethod(type)
                                ),
                            converterInterfaceType),
                        converterInterfaceType.GetMethod("Convert"),
                        srcParam, ctxtParam
                        ),
                    srcParam, destParam, ctxtParam);
            }

            if (typeMap.CustomMapper != null)
            {
                return Lambda(typeMap.CustomMapper.ReplaceParameters(srcParam, destParam, ctxtParam), srcParam,
                    destParam, ctxtParam);
            }

            if (typeMap.CustomProjection != null)
            {
                return Lambda(typeMap.CustomProjection.ReplaceParameters(srcParam), srcParam, destParam, ctxtParam);
            }

            ParameterExpression contextToReuse = null;

            var destinationFunc = CreateDestinationFunc(typeMap, typeMapRegistry, srcParam, destParam, ctxtParam, ref contextToReuse);

            var assignmentFunc = CreateAssignmentFunc(typeMap, configurationProvider, typeMapRegistry, srcParam, destParam, ctxtParam, destinationFunc, ref contextToReuse);

            var mapperFunc = CreateMapperFunc(typeMap, srcParam, destParam, ctxtParam, assignmentFunc);

            var lambdaExpr = Lambda(mapperFunc, srcParam, destParam, ctxtParam);

            return lambdaExpr;
        }
Exemple #38
0
        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) && configurationProvider.ResolveTypeMap(sourceElementType, destElementType) == null)
            {
                // return (TDestination[]) source;
                var convertExpr = Convert(sourceExpression, destElementType.MakeArrayType());

                if (configurationProvider.Configuration.AllowNullCollections)
                {
                    return(convertExpr);
                }

                // return (TDestination[]) source ?? new TDestination[0];
                return(Coalesce(convertExpr, NewArrayBounds(destElementType, Constant(0))));
            }

            var ifNullExpr = configurationProvider.Configuration.AllowNullCollections
                                 ? (Expression)Constant(null, destExpression.Type)
                                 : 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, "destinationArray");
            var indexParam = Parameter(typeof(int), "destinationArrayIndex");

            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 TryPropertyMap(
            PropertyMap pm,
            IConfigurationProvider configurationProvider,
            TypeMapRegistry registry,
            ParameterExpression srcParam,
            ParameterExpression destParam,
            ParameterExpression ctxtParam,
            ref ParameterExpression propertyContext)
        {
            var pmExpression = CreatePropertyMapFunc(pm, configurationProvider, registry, srcParam, destParam, ctxtParam, ref propertyContext);

            if (pmExpression == null)
                return null;

            var autoMapException = Parameter(typeof (AutoMapperMappingException), "ex");
            var exception = Parameter(typeof (Exception), "ex");

            var mappingExceptionCtor =
                typeof (AutoMapperMappingException).GetTypeInfo()
                    .DeclaredConstructors.First(ci => ci.GetParameters().Length == 3);

            return TryCatch(Block(typeof (void), pmExpression),
                MakeCatchBlock(typeof (AutoMapperMappingException), autoMapException,
                    Block(Assign(Property(autoMapException, "PropertyMap"), Constant(pm)), Rethrow()), null),
                MakeCatchBlock(typeof (Exception), exception,
                    Throw(New(mappingExceptionCtor, ctxtParam, exception, Constant(pm))), null));
        }
 public Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider, Expression sourceExpression, Expression destExpression, Expression contextExpression)
 {
     return(sourceExpression);
 }
        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;
        }
 public Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider, PropertyMap propertyMap, Expression sourceExpression, Expression destExpression, Expression contextExpression)
 {
     return sourceExpression;
 }