Ejemplo n.º 1
0
 protected override Expression CreateBlockExpression(Expression source, Expression destination, CompileArgument arg)
 {
     if (destination.Type.IsArray)
     {
         if (source.Type.IsArray && source.Type.GetElementType() == destination.Type.GetElementType())
         {
             //Array.Copy(src, 0, dest, 0, src.Length)
             var method = typeof (Array).GetMethod("Copy", new[] {typeof (Array), typeof (int), typeof (Array), typeof (int), typeof (int)});
             return Expression.Call(method, source, Expression.Constant(0), destination, Expression.Constant(0), Expression.ArrayLength(source));
         }
         else
             return CreateArraySet(source, destination, arg);
     }
     else
     {
         var destinationElementType = destination.Type.ExtractCollectionType();
         var listType = destination.Type.GetGenericEnumerableType() != null
             ? typeof(ICollection<>).MakeGenericType(destinationElementType)
             : typeof(IList);
         var tmp = Expression.Variable(listType);
         var assign = ExpressionEx.Assign(tmp, destination); //convert to list type
         var set = CreateListSet(source, tmp, arg);
         return Expression.Block(new[] {tmp}, assign, set);
     }
 }
Ejemplo n.º 2
0
        protected override Expression CreateBlockExpression(Expression source, Expression destination, CompileArgument arg)
        {
            //### !IgnoreNullValues
            //dest.Prop1 = convert(src.Prop1);
            //dest.Prop2 = convert(src.Prop2);

            //### IgnoreNullValues
            //if (src.Prop1 != null)
            //  dest.Prop1 = convert(src.Prop1);
            //if (src.Prop2 != null)
            //  dest.Prop2 = convert(src.Prop2);

            var properties = CreateAdapterModel(source, destination, arg);

            var lines = new List<Expression>();
            foreach (var property in properties)
            {
                var getter = CreateAdaptExpression(property.Getter, property.Setter.Type, arg);

                Expression itemAssign = Expression.Assign(property.Setter, getter);
                if (arg.Settings.IgnoreNullValues == true && (!property.Getter.Type.GetTypeInfo().IsValueType || property.Getter.Type.IsNullable()))
                {
                    var condition = Expression.NotEqual(property.Getter, Expression.Constant(null, property.Getter.Type));
                    itemAssign = Expression.IfThen(condition, itemAssign);
                }
                lines.Add(itemAssign);
            }

            return Expression.Block(lines);
        }
Ejemplo n.º 3
0
 public LambdaExpression CreateAdaptToTargetFunc(CompileArgument arg)
 {
     var p = Expression.Parameter(arg.SourceType);
     var p2 = Expression.Parameter(arg.DestinationType);
     var body = CreateExpressionBody(p, p2, arg);
     return Expression.Lambda(body, p, p2);
 }
Ejemplo n.º 4
0
        protected override Expression CreateExpressionBody(Expression source, Expression destination, CompileArgument arg)
        {
            Expression convert = source;
            var sourceType = arg.SourceType;
            var destinationType = arg.DestinationType;
            if (sourceType != destinationType)
            {
                if (sourceType.IsNullable())
                {
                    convert = Expression.Convert(convert, sourceType.GetGenericArguments()[0]);
                }
                convert = ReflectionUtils.BuildUnderlyingTypeConvertExpression(convert, sourceType, destinationType);
                if (convert.Type != destinationType)
                    convert = Expression.Convert(convert, destinationType);

                if (arg.MapType != MapType.Projection
                    && (!arg.SourceType.GetTypeInfo().IsValueType || arg.SourceType.IsNullable()))
                {
                    //src == null ? default(TDestination) : convert(src)
                    var compareNull = Expression.Equal(source, Expression.Constant(null, sourceType));
                    convert = Expression.Condition(compareNull, Expression.Constant(destinationType.GetDefault(), destinationType), convert);
                }
            }

            return convert;
        }
Ejemplo n.º 5
0
 protected override bool CanInline(Expression source, Expression destination, CompileArgument arg)
 {
     if (!base.CanInline(source, destination, arg))
         return false;
     if (arg.MapType != MapType.Projection &&
         arg.Settings.IgnoreNullValues == true)
         return false;
     return true;
 }
Ejemplo n.º 6
0
        protected override Expression CreateExpressionBody(Expression source, Expression destination, CompileArgument arg)
        {
            if (arg.IsInvalidRequiredExplicitMapping)
            {
                throw new InvalidOperationException(
                    $"Implicit mapping is not allowed (check GlobalSettings.RequireExplicitMapping) and no configuration exists for the following mapping: TSource: {arg.SourceType} TDestination: {arg.DestinationType}");
            }

            return base.CreateExpressionBody(source, destination, arg);
        }
Ejemplo n.º 7
0
        protected ClassMapping CreateClassConverter(Expression source, Expression destination, CompileArgument arg)
        {
            var classModel = GetClassModel(arg.DestinationType);
            var destinationMembers = classModel.Members;

            var unmappedDestinationMembers = new List<string>();

            var properties = new List<MemberMapping>();

            foreach (var destinationMember in destinationMembers)
            {
                if (ProcessIgnores(arg.Settings, destinationMember)) continue;

                var member = destinationMember;
                var getter = arg.Settings.ValueAccessingStrategies
                    .Select(fn => fn(source, member, arg))
                    .FirstOrDefault(result => result != null);

                if (getter != null)
                {
                    var propertyModel = new MemberMapping
                    {
                        Getter = getter,
                        Setter = destinationMember.GetExpression(destination),
                        SetterInfo = destinationMember.Info,
                    };
                    properties.Add(propertyModel);
                }
                else if (classModel.ConstructorInfo != null)
                {
                    var propertyModel = new MemberMapping
                    {
                        Getter = null,
                        Setter = destinationMember.GetExpression(destination),
                        SetterInfo = destinationMember.Info,
                    };
                    properties.Add(propertyModel);
                }
                else if (destinationMember.SetterModifier != AccessModifier.None)
                {
                    unmappedDestinationMembers.Add(destinationMember.Name);
                }
            }

            if (arg.Context.Config.RequireDestinationMemberSource && unmappedDestinationMembers.Count > 0)
            {
                throw new ArgumentOutOfRangeException($"The following members of destination class {arg.DestinationType} do not have a corresponding source member mapped or ignored:{string.Join(",", unmappedDestinationMembers)}");
            }

            return new ClassMapping
            {
                ConstructorInfo = classModel.ConstructorInfo,
                Members = properties,
            };
        }
Ejemplo n.º 8
0
        private static IEnumerable<PropertyModel> CreateAdapterModel(Expression source, Expression destination, CompileArgument arg)
        {
            Type sourceType = source.Type;
            var destinationMembers = arg.DestinationType.GetPublicFieldsAndProperties(allowNoSetter: false);

            var unmappedDestinationMembers = new List<string>();

            var properties = new List<PropertyModel>();

            for (int i = 0; i < destinationMembers.Count; i++)
            {
                MemberInfo destinationMember = destinationMembers[i];
                bool isProperty = destinationMember is PropertyInfo;

                if (ProcessIgnores(arg.Settings, destinationMember)) continue;

                if (ProcessCustomResolvers(source, destination, arg.Settings, destinationMember, properties)) continue;

                MemberInfo sourceMember = ReflectionUtils.GetPublicFieldOrProperty(sourceType, isProperty, destinationMember.Name);
                if (sourceMember != null)
                {
                    var propertyModel = new PropertyModel
                    {
                        ConvertType = 1,
                        Getter = sourceMember is PropertyInfo
                            ? Expression.Property(source, (PropertyInfo)sourceMember)
                            : Expression.Field(source, (FieldInfo)sourceMember),
                        Setter = destinationMember is PropertyInfo
                            ? Expression.Property(destination, (PropertyInfo) destinationMember)
                            : Expression.Field(destination, (FieldInfo) destinationMember),
                        SetterProperty = destinationMember,
                    };
                    properties.Add(propertyModel);
                }
                else
                {
                    if (FlattenMethod(source, destination, destinationMember, properties)) continue;

                    if (FlattenClass(source, destination, destinationMember, properties, arg.MapType == MapType.Projection)) continue;

                    if (destinationMember.HasPublicSetter())
                    {
                        unmappedDestinationMembers.Add(destinationMember.Name);
                    }
                }
            }

            if (arg.Context.Config.RequireDestinationMemberSource && unmappedDestinationMembers.Count > 0)
            {
                throw new ArgumentOutOfRangeException($"The following members of destination class {arg.DestinationType} do not have a corresponding source member mapped or ignored:{string.Join(",", unmappedDestinationMembers)}");
            }

            return properties;
        }
Ejemplo n.º 9
0
 protected virtual bool CanInline(Expression source, Expression destination, CompileArgument arg)
 {
     if (destination != null)
         return false;
     if (arg.Settings.ConstructUsing != null && arg.Settings.ConstructUsing.Body.NodeType != ExpressionType.New)
         return false;
     if (arg.Settings.PreserveReference == true &&
         arg.MapType != MapType.Projection &&
         !arg.SourceType.GetTypeInfo().IsValueType &&
         !arg.DestinationType.GetTypeInfo().IsValueType)
         return false;
     return true;
 }
Ejemplo n.º 10
0
        protected override Expression CreateBlockExpression(Expression source, Expression destination, CompileArgument arg)
        {
            //### !IgnoreNullValues
            //dict.Add("Prop1", convert(src.Prop1));
            //dict.Add("Prop2", convert(src.Prop2));

            //### IgnoreNullValues
            //if (src.Prop1 != null)
            //  dict.Add("Prop1", convert(src.Prop1));
            //if (src.Prop2 != null)
            //  dict.Add("Prop2", convert(src.Prop2));

            var dictType = destination.Type.GetDictionaryType();
            var valueType = dictType.GetGenericArguments()[1];
            var indexer = dictType.GetProperties().First(item => item.GetIndexParameters().Length > 0);
            var lines = new List<Expression>();

            var dict = Expression.Variable(dictType);
            lines.Add(Expression.Assign(dict, destination));

            MethodInfo setMethod = null;
            var strategy = arg.Settings.NameMatchingStrategy;
            if (arg.MapType == MapType.MapToTarget && strategy.DestinationMemberNameConverter != NameMatchingStrategy.Identity)
            {
                var args = dictType.GetGenericArguments();
                setMethod = typeof (Extensions).GetMethods().First(m => m.Name == "FlexibleSet")
                    .MakeGenericMethod(args[1]);
            }
            var properties = source.Type.GetPublicFieldsAndProperties();
            foreach (var property in properties)
            {
                var getter = property.GetExpression(source);
                var value = CreateAdaptExpression(getter, valueType, arg);

                var sourceMemberName = strategy.SourceMemberNameConverter(property.Name);
                Expression key = Expression.Constant(sourceMemberName);

                var itemSet = setMethod != null
                    ? (Expression)Expression.Call(setMethod, dict, key, Expression.Constant(strategy.DestinationMemberNameConverter), value)
                    : Expression.Assign(Expression.Property(dict, indexer, key), value);
                if (arg.Settings.IgnoreNullValues == true && (!getter.Type.GetTypeInfo().IsValueType || getter.Type.IsNullable()))
                {
                    var condition = Expression.NotEqual(getter, Expression.Constant(null, getter.Type));
                    itemSet = Expression.IfThen(condition, itemSet);
                }
                lines.Add(itemSet);
            }

            return Expression.Block(new[] {dict}, lines);
        }
Ejemplo n.º 11
0
        protected virtual Expression CreateExpressionBody(Expression source, Expression destination, CompileArgument arg)
        {
            if (this.CheckExplicitMapping
                && arg.Context.Config.RequireExplicitMapping
                && !arg.Context.Config.RuleMap.ContainsKey(new TypeTuple(arg.SourceType, arg.DestinationType)))
            {
                throw new InvalidOperationException(
                    $"Implicit mapping is not allowed (check GlobalSettings.RequireExplicitMapping) and no configuration exists for the following mapping: TSource: {arg.SourceType} TDestination: {arg.DestinationType}");
            }

            return CanInline(source, destination, arg)
                ? CreateInlineExpressionBody(source, arg).To(arg.DestinationType, true)
                : CreateBlockExpressionBody(source, destination, arg);
        }
Ejemplo n.º 12
0
        protected override Expression CreateInlineExpression(Expression source, CompileArgument arg)
        {
            var newInstance = (NewExpression)CreateInstantiationExpression(source, arg);
            var properties = CreateAdapterModel(source, newInstance, arg);

            var lines = new List<MemberBinding>();
            foreach (var property in properties)
            {
                var getter = CreateAdaptExpression(property.Getter, property.Setter.Type, arg);
                var bind = Expression.Bind(property.SetterProperty, getter);
                lines.Add(bind);
            }

            return Expression.MemberInit(newInstance, lines);
        }
Ejemplo n.º 13
0
        protected Expression CreateBlockExpressionBody(Expression source, Expression destination, CompileArgument arg)
        {
            var result = Expression.Variable(arg.DestinationType);
            Expression assign = Expression.Assign(result, destination ?? CreateInstantiationExpression(source, arg));

            var set = CreateBlockExpression(source, result, arg);

            if (arg.Settings.PreserveReference == true &&
                arg.MapType != MapType.Projection &&
                !arg.SourceType.GetTypeInfo().IsValueType &&
                !arg.DestinationType.GetTypeInfo().IsValueType)
            {
                var dict = Expression.Parameter(typeof (Dictionary<object, object>));
                var propInfo = typeof(MapContext).GetProperty("Context", BindingFlags.Static | BindingFlags.Public);
                var refContext = Expression.Property(null, propInfo);
                var refDict = Expression.Property(refContext, "References");

                var refAdd = Expression.Call(dict, "Add", null, Expression.Convert(source, typeof(object)), Expression.Convert(result, typeof(object)));
                set = Expression.Block(assign, refAdd, set);

                var cached = Expression.Variable(typeof(object));
                var tryGetMethod = typeof(Dictionary<object, object>).GetMethod("TryGetValue", new[] { typeof(object), typeof(object).MakeByRefType() });
                var checkHasRef = Expression.Call(dict, tryGetMethod, source, cached);
                var assignDict = Expression.Assign(dict, refDict);
                set = Expression.IfThenElse(
                    checkHasRef,
                    ExpressionEx.Assign(result, cached),
                    set);
                set = Expression.Block(new[] { cached, dict }, assignDict, set);
            }
            else
            {
                set = Expression.Block(assign, set);
            }

            if (arg.MapType != MapType.Projection && 
                (!arg.SourceType.GetTypeInfo().IsValueType || arg.SourceType.IsNullable()))
            {
                var compareNull = Expression.Equal(source, Expression.Constant(null, source.Type));
                set = Expression.IfThenElse(
                    compareNull,
                    Expression.Assign(result, destination ?? Expression.Constant(arg.DestinationType.GetDefault(), arg.DestinationType)),
                    set);
            }

            return Expression.Block(new[] { result }, set, result);
        }
Ejemplo n.º 14
0
        protected Expression CreateAdaptExpression(Expression source, Type destinationType, CompileArgument arg)
        {
            if (source.Type == destinationType && (arg.Settings.ShallowCopyForSameType == true || arg.MapType == MapType.Projection))
                return source.To(destinationType);

            var lambda = arg.Context.Config.CreateInlineMapExpression(source.Type, destinationType, arg.MapType, arg.Context);
            var exp = lambda.Apply(source);

            if (arg.Settings.DestinationTransforms.Transforms.ContainsKey(exp.Type))
            {
                var transform = arg.Settings.DestinationTransforms.Transforms[exp.Type];
                var replacer = new ParameterExpressionReplacer(transform.Parameters, exp);
                var newExp = replacer.Visit(transform.Body);
                exp = replacer.ReplaceCount >= 2 ? Expression.Invoke(transform, exp) : newExp;
            }
            return exp.To(destinationType);
        }
Ejemplo n.º 15
0
        protected override Expression CreateInstantiationExpression(Expression source, CompileArgument arg)
        {
            var destinationElementType = arg.DestinationType.ExtractCollectionType();
            if (arg.DestinationType.IsArray)
                return Expression.NewArrayBounds(destinationElementType, CreateCountExpression(source, true));

            var count = CreateCountExpression(source, false);
            var listType = arg.DestinationType.GetTypeInfo().IsInterface
                ? typeof (List<>).MakeGenericType(destinationElementType)
                : arg.DestinationType;
            if (count == null)
                return Expression.New(listType);
            var ctor = listType.GetConstructor(new[] { typeof(int) });
            if (ctor == null)
                return Expression.New(listType);
            else
                return Expression.New(ctor, count);
        }
Ejemplo n.º 16
0
 protected override Expression CreateBlockExpression(Expression source, Expression destination, CompileArgument arg)
 {
     if (destination.Type.IsArray)
     {
         return CreateArraySet(source, destination, arg);
     }
     else
     {
         var destinationElementType = destination.Type.ExtractCollectionType();
         var listType = destination.Type.IsGenericEnumerableType() || destination.Type.GetInterfaces().Any(ReflectionUtils.IsGenericEnumerableType)
             ? typeof(ICollection<>).MakeGenericType(destinationElementType)
             : typeof(IList);
         var tmp = Expression.Variable(listType);
         var assign = ExpressionEx.Assign(tmp, destination); //convert to list type
         var set = CreateListSet(source, tmp, arg);
         return Expression.Block(new[] {tmp}, assign, set);
     }
 }
Ejemplo n.º 17
0
        protected override Expression CreateInlineExpression(Expression source, CompileArgument arg)
        {
            if (arg.DestinationType.GetTypeInfo().IsAssignableFrom(source.Type.GetTypeInfo()) && (arg.Settings.ShallowCopyForSameType == true || arg.MapType == MapType.Projection))
                return source.To(arg.DestinationType);

            var sourceElementType = source.Type.ExtractCollectionType();
            var destinationElementType = arg.DestinationType.ExtractCollectionType();
            var method = (from m in typeof (Enumerable).GetMethods()
                          where m.Name == "Select"
                          let p = m.GetParameters()[1]
                          where p.ParameterType.GetGenericTypeDefinition() == typeof (Func<,>)
                          select m).First().MakeGenericMethod(sourceElementType, destinationElementType);

            var p1 = Expression.Parameter(sourceElementType);
            var adapt = CreateAdaptExpression(p1, destinationElementType, arg);
            if (adapt == p1)
                return source;
            return Expression.Call(method, source, Expression.Lambda(adapt, p1));
        }
Ejemplo n.º 18
0
        protected override Expression CreateInlineExpression(Expression source, CompileArgument arg)
        {
            //new TDestination {
            //  Prop1 = convert(src.Prop1),
            //  Prop2 = convert(src.Prop2),
            //}

            var exp = CreateInstantiationExpression(source, arg);
            var memberInit = exp as MemberInitExpression;
            var newInstance = memberInit?.NewExpression ?? (NewExpression)exp;

            var classConverter = CreateClassConverter(source, newInstance, arg);
            var properties = classConverter.Members;

            var lines = new List<MemberBinding>();
            if (memberInit != null)
                lines.AddRange(memberInit.Bindings);
            foreach (var property in properties)
            {
                var getter = CreateAdaptExpression(property.Getter, property.Setter.Type, arg);

                //special null property check for projection
                //if we don't set null to property, EF will create empty object
                //except collection type & complex type which cannot be null
                if (arg.MapType == MapType.Projection
                    && property.Getter.Type != property.Setter.Type
                    && !property.Getter.Type.IsCollection()
                    && !property.Setter.Type.IsCollection()
                    && property.Getter.Type.GetTypeInfo().GetCustomAttributes(true).All(attr => attr.GetType().Name != "ComplexTypeAttribute")
                    && (!property.Getter.Type.GetTypeInfo().IsValueType || property.Getter.Type.IsNullable()))
                {
                    var compareNull = Expression.Equal(property.Getter, Expression.Constant(null, property.Getter.Type));
                    getter = Expression.Condition(
                        compareNull,
                        Expression.Constant(property.Setter.Type.GetDefault(), property.Setter.Type),
                        getter);
                }
                var bind = Expression.Bind((MemberInfo)property.SetterInfo, getter);
                lines.Add(bind);
            }

            return Expression.MemberInit(newInstance, lines);
        }
Ejemplo n.º 19
0
        protected override bool CanInline(Expression source, Expression destination, CompileArgument arg)
        {
            if (!base.CanInline(source, destination, arg))
                return false;

            if (arg.MapType == MapType.Projection)
            {
                if (arg.DestinationType.IsAssignableFromList())
                    return true;

                throw new InvalidOperationException(
                    $"{arg.DestinationType} is not supported for projection, please consider using List<>: TSource: {arg.SourceType} TDestination: {arg.DestinationType}");
            }

            if (arg.DestinationType == typeof (IEnumerable) || arg.DestinationType.IsGenericEnumerableType())
                return true;

            return false;
        }
Ejemplo n.º 20
0
 protected virtual bool CanInline(Expression source, Expression destination, CompileArgument arg)
 {
     if (arg.MapType == MapType.MapToTarget)
         return false;
     if (arg.Settings.ConstructUsing != null &&
         arg.Settings.ConstructUsing.Body.NodeType != ExpressionType.New &&
         arg.Settings.ConstructUsing.Body.NodeType != ExpressionType.MemberInit)
     {
         if (arg.MapType == MapType.Projection)
             throw new InvalidOperationException(
                 $"Input ConstructUsing is invalid for projection: TSource: {arg.SourceType} TDestination: {arg.DestinationType}");
         return false;
     }
     if (arg.Settings.PreserveReference == true &&
         arg.MapType != MapType.Projection &&
         !arg.SourceType.GetTypeInfo().IsValueType &&
         !arg.DestinationType.GetTypeInfo().IsValueType)
         return false;
     return true;
 }
Ejemplo n.º 21
0
        protected override Expression CreateInstantiationExpression(Expression source, CompileArgument arg)
        {
            var destinationElementType = arg.DestinationType.ExtractCollectionType();
            if (arg.DestinationType.IsArray)
                return Expression.NewArrayBounds(
                    destinationElementType, 
                    CreateCountExpression(source, true));   //new TDestinationElement[count]

            var count = CreateCountExpression(source, false);
            var listType = arg.DestinationType.GetTypeInfo().IsInterface
                ? typeof (List<>).MakeGenericType(destinationElementType)
                : arg.DestinationType;
            if (count == null)
                return Expression.New(listType);            //new List<T>()
            var ctor = (from c in listType.GetConstructors()
                        let args = c.GetParameters()
                        where args.Length == 1 && args[0].ParameterType == typeof (int)
                        select c).FirstOrDefault();
            if (ctor == null)
                return Expression.New(listType);            //new List<T>()
            else
                return Expression.New(ctor, count);         //new List<T>(count)
        }
Ejemplo n.º 22
0
        protected override Expression CreateInstantiationExpression(Expression source, CompileArgument arg)
        {
            //new TDestination(src.Prop1, src.Prop2)

            if (arg.Settings.ConstructUsingFactory != null)
                return base.CreateInstantiationExpression(source, arg);

            var classConverter = CreateClassConverter(source, null, arg);
            var properties = classConverter.Members;

            var arguments = new List<Expression>();
            foreach (var property in properties)
            {
                var parameterInfo = (ParameterInfo) property.SetterInfo;
                var defaultValue = parameterInfo.IsOptional ? parameterInfo.DefaultValue : parameterInfo.ParameterType.GetDefault();

                Expression getter;
                if (property.Getter == null)
                {
                    getter = Expression.Constant(defaultValue, property.Setter.Type);
                }
                else
                {
                    getter = CreateAdaptExpression(property.Getter, property.Setter.Type, arg);

                    if (arg.Settings.IgnoreNullValues == true && (!property.Getter.Type.GetTypeInfo().IsValueType || property.Getter.Type.IsNullable()))
                    {
                        var condition = Expression.NotEqual(property.Getter, Expression.Constant(null, property.Getter.Type));
                        getter = Expression.Condition(condition, getter, Expression.Constant(defaultValue, property.Setter.Type));
                    }
                }
                arguments.Add(getter);
            }

            return Expression.New(classConverter.ConstructorInfo, arguments);
        }
Ejemplo n.º 23
0
        protected override Expression CreateInlineExpression(Expression source, CompileArgument arg)
        {
            //new TDestination {
            //  { "Prop1", convert(src.Prop1) },
            //  { "Prop2", convert(src.Prop2) },
            //}

            var exp = CreateInstantiationExpression(source, arg);
            var listInit = exp as ListInitExpression;
            var newInstance = listInit?.NewExpression ?? (NewExpression)exp;

            var dictType = arg.DestinationType.GetDictionaryType();
            var dictTypeArgs = dictType.GetGenericArguments();
            var keyType = dictTypeArgs[0];
            var valueType = dictTypeArgs[1];
            var add = dictType.GetMethod("Add", new[] { keyType, valueType });
            var lines = new List<ElementInit>();
            if (listInit != null)
                lines.AddRange(listInit.Initializers);

            var nameMatching = arg.Settings.NameMatchingStrategy;
            var properties = source.Type.GetPublicFieldsAndProperties();
            foreach (var property in properties)
            {
                var getter = property.GetExpression(source);
                var value = CreateAdaptExpression(getter, valueType, arg);

                Expression key = Expression.Constant(nameMatching.SourceMemberNameConverter(property.Name));
                key = CreateAdaptExpression(key, keyType, arg);

                var itemInit = Expression.ElementInit(add, key, value);
                lines.Add(itemInit);
            }

            return Expression.ListInit(newInstance, lines);
        }
Ejemplo n.º 24
0
        private static Expression InvokeMapping(Func <CompileArgument, LambdaExpression> mappingFactory, Expression source, Expression result, CompileArgument arg, bool setResult)
        {
            var afterMapping = mappingFactory(arg);
            var args         = afterMapping.Parameters;
            var invoke       = afterMapping.Apply(arg.MapType, source.To(args[0].Type), result.To(args[1].Type));

            if (invoke.Type != typeof(void) && setResult)
            {
                invoke = ExpressionEx.Assign(result, invoke);
            }
            return(invoke);
        }
Ejemplo n.º 25
0
 protected override Expression CreateInstantiationExpression(Expression source, Expression?destination, CompileArgument arg)
 {
     return(Expression.NewArrayBounds(arg.DestinationType.GetElementType(), GetArrayBounds(source, arg.DestinationType)));
 }
Ejemplo n.º 26
0
        protected virtual Expression CreateExpressionBody(Expression source, Expression?destination, CompileArgument arg)
        {
            if (this.CheckExplicitMapping && arg.Context.Config.RequireExplicitMapping && !arg.ExplicitMapping)
            {
                throw new InvalidOperationException("Implicit mapping is not allowed (check GlobalSettings.RequireExplicitMapping) and no configuration exists");
            }

            var oldMaxDepth = arg.Context.MaxDepth;
            var oldDepth    = arg.Context.Depth;

            try
            {
                if (!arg.Context.MaxDepth.HasValue && arg.Settings.MaxDepth.HasValue)
                {
                    arg.Context.MaxDepth = arg.Settings.MaxDepth;
                    arg.Context.Depth    = 0;
                }
                if (arg.Context.MaxDepth.HasValue)
                {
                    if (this.ObjectType != ObjectType.Primitive && arg.Context.Depth >= arg.Context.MaxDepth.Value)
                    {
                        return(arg.DestinationType.CreateDefault());
                    }
                    if (this.ObjectType == ObjectType.Class)
                    {
                        arg.Context.Depth++;
                    }
                }

                if (CanInline(source, destination, arg))
                {
                    var exp = CreateInlineExpressionBody(source, arg);
                    if (exp != null)
                    {
                        return(exp.To(arg.DestinationType, true));
                    }
                }

                if (arg.Context.Running.Count > 1 &&
                    !arg.Context.Config.SelfContainedCodeGeneration &&
                    !arg.UseDestinationValue &&
                    !arg.Context.IsSubFunction())
                {
                    if (destination == null)
                    {
                        return(arg.Context.Config.CreateMapInvokeExpressionBody(source.Type, arg.DestinationType, source));
                    }
                    else
                    {
                        return(arg.Context.Config.CreateMapToTargetInvokeExpressionBody(source.Type, arg.DestinationType, source, destination));
                    }
                }
                else
                {
                    return(CreateBlockExpressionBody(source, destination, arg));
                }
            }
            finally
            {
                arg.Context.Depth    = oldDepth;
                arg.Context.MaxDepth = oldMaxDepth;
            }
        }
Ejemplo n.º 27
0
 protected abstract Expression CreateBlockExpression(Expression source, Expression destination, CompileArgument arg);
Ejemplo n.º 28
0
        private static Expression CreateAdaptExpressionCore(Expression source, Type destinationType, CompileArgument arg, MemberMapping?mapping = null, Expression?destination = null)
        {
            var mapType = arg.MapType == MapType.MapToTarget && destination == null ? MapType.Map :
                          mapping?.UseDestinationValue == true ? MapType.MapToTarget :
                          arg.MapType;
            var extraParams = new HashSet <ParameterExpression>();

            try
            {
                if (mapping != null && mapping.HasSettings())
                {
                    if (arg.Context.ExtraParameters.Add(mapping.Source))
                    {
                        extraParams.Add(mapping.Source);
                    }
                    if (mapping.Destination != null && arg.Context.ExtraParameters.Add(mapping.Destination))
                    {
                        extraParams.Add(mapping.Destination);
                    }
                }
                var lambda    = arg.Context.Config.CreateInlineMapExpression(source.Type, destinationType, mapType, arg.Context, mapping);
                var paramList = new List <Expression> {
                    source
                };
                if (destination != null)
                {
                    paramList.Add(destination);
                }
                paramList.AddRange(lambda.Parameters.Skip(paramList.Count));
                if (!lambda.IsMultiLine())
                {
                    return(lambda.Apply(arg.MapType, paramList.ToArray()));
                }
                return(Expression.Invoke(lambda, paramList.ToArray()));
            }
            finally
            {
                arg.Context.ExtraParameters.ExceptWith(extraParams);
            }
        }
Ejemplo n.º 29
0
        protected virtual Expression CreateInstantiationExpression(Expression source, CompileArgument arg)
        {
            //new TDestination()

            return arg.Settings.ConstructUsing != null
                ? arg.Settings.ConstructUsing.Apply(source).TrimConversion().To(arg.DestinationType)
                : Expression.New(arg.DestinationType);
        }
Ejemplo n.º 30
0
        protected Expression CreateBlockExpressionBody(Expression source, Expression?destination, CompileArgument arg)
        {
            if (arg.MapType == MapType.Projection)
            {
                throw new InvalidOperationException("Mapping is invalid for projection");
            }

            var vars   = new List <ParameterExpression>();
            var blocks = new List <Expression>();
            var label  = Expression.Label(arg.DestinationType);

            //var drvdSource = source as TDerivedSource
            //if (drvdSource != null)
            //  return adapt<TSource, TDest>(drvdSource);
            foreach (var tuple in arg.Settings.Includes)
            {
                //same type, no redirect to prevent endless loop
                if (tuple.Source == arg.SourceType)
                {
                    continue;
                }

                //type is not compatible, no redirect
                if (!arg.SourceType.GetTypeInfo().IsAssignableFrom(tuple.Source.GetTypeInfo()))
                {
                    continue;
                }

                var drvdSource = Expression.Variable(tuple.Source);
                vars.Add(drvdSource);

                var drvdSourceAssign = Expression.Assign(
                    drvdSource,
                    Expression.TypeAs(source, tuple.Source));
                blocks.Add(drvdSourceAssign);
                var cond = Expression.NotEqual(drvdSource, Expression.Constant(null, tuple.Source));

                ParameterExpression?drvdDest = null;
                if (destination != null)
                {
                    drvdDest = Expression.Variable(tuple.Destination);
                    vars.Add(drvdDest);

                    var drvdDestAssign = Expression.Assign(
                        drvdDest,
                        Expression.TypeAs(destination, tuple.Destination));
                    blocks.Add(drvdDestAssign);
                    cond = Expression.AndAlso(
                        cond,
                        Expression.NotEqual(drvdDest, Expression.Constant(null, tuple.Destination)));
                }

                var adaptExpr = CreateAdaptExpressionCore(drvdSource, tuple.Destination, arg, destination: drvdDest);
                var adapt     = Expression.Return(label, adaptExpr);
                var ifExpr    = Expression.IfThen(cond, adapt);
                blocks.Add(ifExpr);
            }

            //new TDest();
            Expression transformedSource = source;
            var        transform         = TransformSource(source);

            if (transform != source)
            {
                var src = Expression.Variable(transform.Type);
                vars.Add(src);
                transformedSource = src;
            }
            var set = CreateInstantiationExpression(transformedSource, destination, arg);

            if (destination != null && (this.UseTargetValue || arg.UseDestinationValue) && arg.GetConstructUsing()?.Parameters.Count != 2 && destination.CanBeNull())
            {
                //dest ?? new TDest();
                set = Expression.Coalesce(destination, set);
            }

            if (set.NodeType == ExpressionType.Throw)
            {
                blocks.Add(set);
            }
            else
            {
                //TDestination result;
                //if (source == null)
                //  return default(TDestination);
                if (source.CanBeNull())
                {
                    var compareNull = Expression.Equal(source, Expression.Constant(null, source.Type));
                    blocks.Add(
                        Expression.IfThen(compareNull,
                                          Expression.Return(label, arg.DestinationType.CreateDefault()))
                        );
                }

                //var result = new TDest();
                var result        = Expression.Variable(arg.DestinationType, "result");
                var assign        = Expression.Assign(result, set);
                var assignActions = new List <Expression>();
                if (transform != source)
                {
                    assignActions.Add(Expression.Assign(transformedSource, transform));
                }
                assignActions.Add(assign);

                //before(source, result);
                var beforeMappings = arg.Settings.BeforeMappingFactories.Select(it => InvokeMapping(it, source, result, arg, true));
                assignActions.AddRange(beforeMappings);

                //result.prop = adapt(source.prop);
                var mapping        = CreateBlockExpression(transformedSource, result, arg);
                var settingActions = new List <Expression> {
                    mapping
                };

                //after(source, result);
                var afterMappings = arg.Settings.AfterMappingFactories.Select(it => InvokeMapping(it, source, result, arg, false));
                settingActions.AddRange(afterMappings);

                //return result;
                settingActions.Add(Expression.Return(label, result));

                //using (var scope = new MapContextScope()) {
                //  var references = scope.Context.Reference;
                //  var key = new ReferenceTuple(source, typeof(TDestination));
                //  if (references.TryGetValue(key, out var cache))
                //      return (TDestination)cache;
                //
                //  var result = new TDestination();
                //  references[source] = (object)result;
                //  result.prop = adapt(source.prop);
                //  return result;
                //}

                if (arg.Settings.PreserveReference == true &&
                    arg.SourceType.IsObjectReference() &&
                    arg.DestinationType.IsObjectReference())
                {
                    var scope = Expression.Variable(typeof(MapContextScope), "scope");
                    vars.Add(scope);

                    var newScope = Expression.Assign(scope, Expression.New(typeof(MapContextScope)));
                    blocks.Add(newScope);

                    var dictType         = typeof(Dictionary <ReferenceTuple, object>);
                    var references       = Expression.Variable(dictType, "references");
                    var refContext       = Expression.Property(scope, "Context");
                    var refDict          = Expression.Property(refContext, "References");
                    var assignReferences = Expression.Assign(references, refDict);

                    var tupleType = typeof(ReferenceTuple);
                    var key       = Expression.Variable(tupleType, "key");
                    var assignKey = Expression.Assign(key,
                                                      Expression.New(tupleType.GetConstructor(new[] { typeof(object), typeof(Type) }) !,
                                                                     source,
                                                                     Expression.Constant(arg.DestinationType)));

                    var cache        = Expression.Variable(typeof(object), "cache");
                    var tryGetMethod = dictType.GetMethod("TryGetValue", new[] { typeof(ReferenceTuple), typeof(object).MakeByRefType() });
                    var checkHasRef  = Expression.Call(references, tryGetMethod !, key, cache);
                    var setResult    = Expression.IfThen(
                        checkHasRef,
                        Expression.Return(label, cache.To(arg.DestinationType)));

                    var indexer   = dictType.GetProperties().First(item => item.GetIndexParameters().Length > 0);
                    var refAssign = Expression.Assign(
                        Expression.Property(references, indexer, key),
                        Expression.Convert(result, typeof(object)));
                    assignActions.Add(refAssign);

                    var usingBody = Expression.Block(
                        new[] { cache, references, key, result },
                        new Expression[] { assignReferences, assignKey, setResult }
                        .Concat(assignActions)
                        .Concat(settingActions));

                    var dispose = Expression.Call(scope, "Dispose", null);
                    blocks.Add(Expression.TryFinally(usingBody, dispose));
                }
                else
                {
                    vars.Add(result);
                    blocks.AddRange(assignActions);
                    blocks.AddRange(settingActions);
                }
            }

            blocks.Add(Expression.Label(label, arg.DestinationType.CreateDefault()));
            return(Expression.Block(vars, blocks));
        }
Ejemplo n.º 31
0
 protected override Expression CreateInlineExpression(Expression source, CompileArgument arg)
 {
     return CreateInstantiationExpression(source, arg);
 }
Ejemplo n.º 32
0
 protected abstract Expression CreateBlockExpression(Expression source, Expression destination, CompileArgument arg);
Ejemplo n.º 33
0
        protected override Expression CreateInstantiationExpression(Expression source, Expression destination, CompileArgument arg)
        {
            var destinationElementType = arg.DestinationType.ExtractCollectionType();
            var count    = ExpressionEx.CreateCountExpression(source, false);
            var listType = arg.DestinationType.GetTypeInfo().IsInterface
                ? typeof(List <>).MakeGenericType(destinationElementType)
                : arg.DestinationType;

            if (count == null)
            {
                return(Expression.New(listType));            //new List<T>()
            }
            var ctor = (from c in listType.GetConstructors()
                        let args = c.GetParameters()
                                   where args.Length == 1 && args[0].ParameterType == typeof(int)
                                   select c).FirstOrDefault();

            if (ctor == null)
            {
                return(Expression.New(listType));            //new List<T>()
            }
            else
            {
                return(Expression.New(ctor, count));         //new List<T>(count)
            }
        }
Ejemplo n.º 34
0
        private Expression CreateArraySet(Expression source, Expression destination, CompileArgument arg)
        {
            //var v0 = 0, v1 = 0;
            //var vlen0 = dest.GetLength(0), vlen1 = dest.GetLength(1);
            //for (var i = 0, len = src.Count; i < len; i++) {
            //  var item = src[i];
            //  dest[v0, v1] = convert(item);
            //  v1++;
            //  if (v1 >= vlen1) {
            //      v1 = 0;
            //      v0++;
            //  }
            //}

            var sourceElementType      = source.Type.ExtractCollectionType();
            var destinationElementType = destination.Type.ExtractCollectionType();
            var item = Expression.Variable(sourceElementType, "item");
            var vx   = Enumerable.Range(0, destination.Type.GetArrayRank())
                       .Select(i => Expression.Variable(typeof(int), "v" + i))
                       .ToList();
            var vlenx = Enumerable.Range(0, destination.Type.GetArrayRank())
                        .Select(i => Expression.Variable(typeof(int), "vlen" + i))
                        .ToList();
            var block = new List <Expression>();

            block.AddRange(vx.Select(v => Expression.Assign(v, Expression.Constant(0))));

            var method = typeof(Array).GetMethod("GetLength", new[] { typeof(int) });

            block.AddRange(
                vlenx.Select((vlen, i) =>
                             Expression.Assign(
                                 vlen,
                                 Expression.Call(destination, method, Expression.Constant(i)))));
            var getter = CreateAdaptExpression(item, destinationElementType, arg);
            var set    = ExpressionEx.Assign(
                Expression.ArrayAccess(destination, vx),
                getter);

            Expression ifExpr = Expression.Block(
                Expression.Assign(vx[1], Expression.Constant(0)),
                Expression.PostIncrementAssign(vx[0]));

            for (var i = 1; i < vx.Count; i++)
            {
                var list = new List <Expression>();
                if (i + 1 < vx.Count)
                {
                    list.Add(Expression.Assign(vx[i + 1], Expression.Constant(0)));
                }
                list.Add(Expression.PostIncrementAssign(vx[i]));
                list.Add(Expression.IfThen(
                             Expression.GreaterThanOrEqual(vx[i], vlenx[i]),
                             ifExpr));
                ifExpr = Expression.Block(list);
            }

            var loop = ExpressionEx.ForLoop(source, item, set, ifExpr);

            block.Add(loop);
            return(Expression.Block(vx.Concat(vlenx), block));
        }
Ejemplo n.º 35
0
 protected Expression CreateAdaptExpression(Expression source, Type destinationType, CompileArgument arg, Expression?destination = null)
 {
     return(CreateAdaptExpression(source, destinationType, arg, null, destination));
 }
Ejemplo n.º 36
0
 protected abstract Expression?CreateInlineExpression(Expression source, CompileArgument arg);
Ejemplo n.º 37
0
 protected override bool CanInline(Expression source, Expression?destination, CompileArgument arg)
 {
     return(false);
 }
Ejemplo n.º 38
0
 protected override Expression CreateInstantiationExpression(Expression source, Expression?destination, CompileArgument arg)
 {
     if (destination == null)
     {
         return(_lambda.Apply(arg.MapType, source));
     }
     else
     {
         return(_lambda.Apply(arg.MapType, source, destination));
     }
 }
Ejemplo n.º 39
0
 protected override Expression CreateBlockExpression(Expression source, Expression destination, CompileArgument arg)
 {
     return(Expression.Empty());
 }
Ejemplo n.º 40
0
        protected override Expression CreateBlockExpression(Expression source, Expression destination, CompileArgument arg)
        {
            //### !IgnoreNullValues
            //dest.Prop1 = convert(src.Prop1);
            //dest.Prop2 = convert(src.Prop2);

            //### IgnoreNullValues
            //if (src.Prop1 != null)
            //  dest.Prop1 = convert(src.Prop1);
            //if (src.Prop2 != null)
            //  dest.Prop2 = convert(src.Prop2);

            var classConverter = CreateClassConverter(source, destination, arg);
            var properties     = classConverter.Members;

            var lines = new List <Expression>();

            foreach (var property in properties)
            {
                var getter = CreateAdaptExpression(property.Getter, property.Setter.Type, arg);

                Expression itemAssign = Expression.Assign(property.Setter, getter);
                if (arg.Settings.IgnoreNullValues == true && (!property.Getter.Type.GetTypeInfo().IsValueType || property.Getter.Type.IsNullable()))
                {
                    var condition = Expression.NotEqual(property.Getter, Expression.Constant(null, property.Getter.Type));
                    itemAssign = Expression.IfThen(condition, itemAssign);
                }
                lines.Add(itemAssign);
            }

            return(Expression.Block(lines));
        }
Ejemplo n.º 41
0
 protected override Expression CreateInlineExpression(Expression source, CompileArgument arg)
 {
     throw new NotImplementedException();
 }
Ejemplo n.º 42
0
        protected override Expression CreateBlockExpression(Expression source, Expression destination, CompileArgument arg)
        {
            var destinationElementType = destination.Type.ExtractCollectionType();
            var listType = destination.Type.GetGenericEnumerableType() != null
                ? typeof(ICollection <>).MakeGenericType(destinationElementType)
                : typeof(IList);
            var tmp    = Expression.Variable(listType, "list");
            var assign = ExpressionEx.Assign(tmp, destination); //convert to list type
            var set    = CreateListSet(source, tmp, arg);

            return(Expression.Block(new[] { tmp }, assign, set));
        }
Ejemplo n.º 43
0
        protected virtual Expression CreateInstantiationExpression(Expression source, Expression?destination, CompileArgument arg)
        {
            //new TDestination()

            //if there is constructUsing, use constructUsing
            var constructUsing = arg.GetConstructUsing();

            if (constructUsing != null)
            {
                var args = destination == null ? new[] { source } : new[] { source, destination };
                return(constructUsing.Apply(arg.MapType, args)
                       .TrimConversion(true)
                       .To(arg.DestinationType));
            }

            //if there is default constructor, use default constructor
            else if (arg.DestinationType.HasDefaultConstructor())
            {
                return(Expression.New(arg.DestinationType));
            }

            //if mapToTarget or include derived types, allow mapping & throw exception on runtime
            //instantiation is not needed
            else if (destination != null || arg.Settings.Includes.Count > 0)
            {
                return(Expression.Throw(
                           Expression.New(
                               // ReSharper disable once AssignNullToNotNullAttribute
                               typeof(InvalidOperationException).GetConstructor(new[] { typeof(string) }),
                               Expression.Constant("Cannot instantiate type: " + arg.DestinationType.Name)),
                           arg.DestinationType));
            }

            //if mapping to interface, create dynamic type implementing it
            else if (arg.DestinationType.GetTypeInfo().IsInterface)
            {
                return(Expression.New(DynamicTypeGenerator.GetTypeForInterface(arg.DestinationType)));
            }

            //otherwise throw
            else
            {
                throw new InvalidOperationException($"No default constructor for type '{arg.DestinationType.Name}', please use 'ConstructUsing' or 'MapWith'");
            }
        }
Ejemplo n.º 44
0
 protected override Expression CreateInlineExpression(Expression source, CompileArgument arg)
 {
     return(CreateInstantiationExpression(source, arg));
 }
Ejemplo n.º 45
0
 protected override Expression CreateBlockExpression(Expression source, Expression destination, CompileArgument arg)
 {
     if (source.Type.IsArray &&
         source.Type.GetArrayRank() == destination.Type.GetArrayRank() &&
         source.Type.GetElementType() == destination.Type.GetElementType() &&
         source.Type.GetElementType().IsPrimitiveKind())
     {
         //Array.Copy(src, 0, dest, 0, src.Length)
         var method = typeof(Array).GetMethod("Copy", new[] { typeof(Array), typeof(int), typeof(Array), typeof(int), typeof(int) });
         return(Expression.Call(method, source, Expression.Constant(0), destination, Expression.Constant(0), ExpressionEx.CreateCountExpression(source, true)));
     }
     else
     {
         return(CreateArraySet(source, destination, arg));
     }
 }
Ejemplo n.º 46
0
        protected Expression CreateBlockExpressionBody(Expression source, Expression destination, CompileArgument arg)
        {
            var result = Expression.Variable(arg.DestinationType);
            Expression assign = Expression.Assign(result, destination ?? CreateInstantiationExpression(source, arg));

            var set = CreateBlockExpression(source, result, arg);

            if (arg.Settings.PreserveReference == true &&
                arg.MapType != MapType.Projection &&
                !arg.SourceType.GetTypeInfo().IsValueType &&
                !arg.DestinationType.GetTypeInfo().IsValueType)
            {
                //using (var scope = new MapContextScope()) {
                //  var dict = scope.Context.Reference;
                //  object cache;
                //  if (dict.TryGetValue(source, out cache))
                //      result = (TDestination)cache;
                //  else {
                //      result = new TDestination();
                //      dict.Add(source, (object)result);
                //      result.Prop1 = adapt(source.Prop1);
                //      result.Prop2 = adapt(source.Prop2);
                //  }
                //}

                var scope = Expression.Variable(typeof(MapContextScope));
                var newScope = Expression.Assign(scope, Expression.New(typeof(MapContextScope)));

                var dict = Expression.Variable(typeof (Dictionary<object, object>));
                var refContext = Expression.Property(scope, "Context");
                var refDict = Expression.Property(refContext, "References");
                var assignDict = Expression.Assign(dict, refDict);

                var refAdd = Expression.Call(dict, "Add", null, Expression.Convert(source, typeof(object)), Expression.Convert(result, typeof(object)));
                var setResultAndCache = Expression.Block(assign, refAdd, set);

                var cached = Expression.Variable(typeof(object));
                var tryGetMethod = typeof(Dictionary<object, object>).GetMethod("TryGetValue", new[] { typeof(object), typeof(object).MakeByRefType() });
                var checkHasRef = Expression.Call(dict, tryGetMethod, source, cached);
                var setResult = Expression.IfThenElse(
                    checkHasRef,
                    ExpressionEx.Assign(result, cached),
                    setResultAndCache);
                var usingBody = Expression.Block(new[] { cached, dict }, assignDict, setResult);

                var dispose = Expression.Call(scope, "Dispose", null);
                set = Expression.Block(new[] { scope }, newScope, Expression.TryFinally(usingBody, dispose));
            }
            else
            {
                set = Expression.Block(assign, set);
            }

            //TDestination result;
            //if (source == null)
            //  result = default(TDestination);
            //else
            //  result = adapt(source);
            //return result;
            if (arg.MapType != MapType.Projection &&
                (!arg.SourceType.GetTypeInfo().IsValueType || arg.SourceType.IsNullable()))
            {
                var compareNull = Expression.Equal(source, Expression.Constant(null, source.Type));
                set = Expression.IfThenElse(
                    compareNull,
                    Expression.Assign(result, destination ?? Expression.Constant(arg.DestinationType.GetDefault(), arg.DestinationType)),
                    set);
            }

            return Expression.Block(new[] { result }, set, result);
        }
Ejemplo n.º 47
0
        internal Expression CreateAdaptExpression(Expression source, Type destinationType, CompileArgument arg, MemberMapping?mapping, Expression?destination = null)
        {
            if (source.Type == destinationType &&
                (arg.Settings.ShallowCopyForSameType == true || arg.MapType == MapType.Projection))
            {
                return(source);
            }

            //adapt(source);
            var exp = CreateAdaptExpressionCore(source, destinationType, arg, mapping, destination);

            //transform(adapt(source));
            var transform = arg.Settings.DestinationTransforms.Find(it => it.Condition(exp.Type));

            if (transform != null)
            {
                exp = transform.TransformFunc(exp.Type).Apply(arg.MapType, exp);
            }
            return(exp.To(destinationType));
        }
Ejemplo n.º 48
0
 protected override Expression CreateBlockExpression(Expression source, Expression destination, CompileArgument arg)
 {
     return Expression.Empty();
 }
Ejemplo n.º 49
0
 protected Expression CreateInstantiationExpression(Expression source, CompileArgument arg)
 {
     return(CreateInstantiationExpression(source, null, arg));
 }
Ejemplo n.º 50
0
 protected override Expression CreateBlockExpression(Expression source, Expression destination, CompileArgument arg)
 {
     throw new NotImplementedException();
 }
Ejemplo n.º 51
0
        protected override Expression CreateInstantiationExpression(Expression source, CompileArgument arg)
        {
            //new TDestination(src.Prop1, src.Prop2)

            if (arg.Settings.ConstructUsingFactory != null)
            {
                return(base.CreateInstantiationExpression(source, arg));
            }

            var classConverter = CreateClassConverter(source, null, arg);
            var properties     = classConverter.Members;

            var arguments = new List <Expression>();

            foreach (var property in properties)
            {
                var parameterInfo = (ParameterInfo)property.SetterInfo;
                var defaultValue  = parameterInfo.IsOptional ? parameterInfo.DefaultValue : parameterInfo.ParameterType.GetDefault();

                Expression getter;
                if (property.Getter == null)
                {
                    getter = Expression.Constant(defaultValue, property.Setter.Type);
                }
                else
                {
                    getter = CreateAdaptExpression(property.Getter, property.Setter.Type, arg);

                    if (arg.Settings.IgnoreNullValues == true && (!property.Getter.Type.GetTypeInfo().IsValueType || property.Getter.Type.IsNullable()))
                    {
                        var condition = Expression.NotEqual(property.Getter, Expression.Constant(null, property.Getter.Type));
                        getter = Expression.Condition(condition, getter, Expression.Constant(defaultValue, property.Setter.Type));
                    }
                }
                arguments.Add(getter);
            }

            return(Expression.New(classConverter.ConstructorInfo, arguments));
        }
Ejemplo n.º 52
0
 protected override Expression CreateInlineExpression(Expression source, CompileArgument arg)
 {
     throw new NotImplementedException();
 }
Ejemplo n.º 53
0
        protected ClassMapping CreateClassConverter(Expression source, Expression destination, CompileArgument arg)
        {
            var classModel         = GetClassModel(arg.DestinationType);
            var destinationMembers = classModel.Members;

            var unmappedDestinationMembers = new List <string>();

            var properties = new List <MemberMapping>();

            foreach (var destinationMember in destinationMembers)
            {
                if (ProcessIgnores(arg.Settings, destinationMember))
                {
                    continue;
                }

                var member = destinationMember;
                var getter = arg.Settings.ValueAccessingStrategies
                             .Select(fn => fn(source, member, arg))
                             .FirstOrDefault(result => result != null);

                if (getter != null)
                {
                    var propertyModel = new MemberMapping
                    {
                        Getter     = getter,
                        Setter     = destinationMember.GetExpression(destination),
                        SetterInfo = destinationMember.Info,
                    };
                    properties.Add(propertyModel);
                }
                else if (classModel.ConstructorInfo != null)
                {
                    var propertyModel = new MemberMapping
                    {
                        Getter     = null,
                        Setter     = destinationMember.GetExpression(destination),
                        SetterInfo = destinationMember.Info,
                    };
                    properties.Add(propertyModel);
                }
                else if (destinationMember.SetterModifier != AccessModifier.None)
                {
                    unmappedDestinationMembers.Add(destinationMember.Name);
                }
            }

            if (arg.Context.Config.RequireDestinationMemberSource && unmappedDestinationMembers.Count > 0)
            {
                throw new ArgumentOutOfRangeException($"The following members of destination class {arg.DestinationType} do not have a corresponding source member mapped or ignored:{string.Join(",", unmappedDestinationMembers)}");
            }

            return(new ClassMapping
            {
                ConstructorInfo = classModel.ConstructorInfo,
                Members = properties,
            });
        }