Пример #1
0
        protected Expression CreateInstantiationExpression(Expression source, ClassMapping classConverter, CompileArgument arg)
        {
            var members = classConverter.Members;

            var arguments = new List <Expression>();

            foreach (var member in members)
            {
                var parameterInfo = (ParameterInfo)member.DestinationMember.Info !;
                var defaultConst  = parameterInfo.IsOptional
                    ? Expression.Constant(parameterInfo.DefaultValue, member.DestinationMember.Type)
                    : parameterInfo.ParameterType.CreateDefault();

                Expression getter;
                if (member.Getter == null)
                {
                    getter = defaultConst;
                }
                else
                {
                    getter = CreateAdaptExpression(member.Getter, member.DestinationMember.Type, arg, member);
                    if (member.Ignore.Condition != null)
                    {
                        var body = member.Ignore.IsChildPath
                            ? member.Ignore.Condition.Body
                            : member.Ignore.Condition.Apply(arg.MapType, source, arg.DestinationType.CreateDefault());
                        var condition = ExpressionEx.Not(body);
                        getter = Expression.Condition(condition, getter, defaultConst);
                    }
                }
                arguments.Add(getter);
            }

            return(Expression.New(classConverter.ConstructorInfo, arguments));
        }
Пример #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 classModel     = GetSetterModel(arg);
            var classConverter = CreateClassConverter(source, classModel, arg, destination);
            var members        = classConverter.Members;

            var lines = new List <Expression>();
            Dictionary <LambdaExpression, Tuple <List <Expression>, Expression> >?conditions = null;

            foreach (var member in members)
            {
                var destMember = arg.MapType == MapType.MapToTarget
                    ? member.DestinationMember.GetExpression(destination)
                    : null;
                var value = CreateAdaptExpression(member.Getter, member.DestinationMember.Type, arg, member, destMember);

                Expression itemAssign = member.DestinationMember.SetExpression(destination, value);
                if (arg.Settings.IgnoreNullValues == true && member.Getter.CanBeNull())
                {
                    var condition = Expression.NotEqual(member.Getter, Expression.Constant(null, member.Getter.Type));
                    itemAssign = Expression.IfThen(condition, itemAssign);
                }

                if (member.Ignore.Condition != null)
                {
                    if (conditions == null)
                    {
                        conditions = new Dictionary <LambdaExpression, Tuple <List <Expression>, Expression> >();
                    }
                    if (!conditions.TryGetValue(member.Ignore.Condition, out var tuple))
                    {
                        var body = member.Ignore.IsChildPath
                            ? member.Ignore.Condition.Body
                            : member.Ignore.Condition.Apply(arg.MapType, source, destination);
                        tuple = Tuple.Create(new List <Expression>(), body);
                        conditions[member.Ignore.Condition] = tuple;
                    }
                    tuple.Item1.Add(itemAssign);
                }
                else
                {
                    lines.Add(itemAssign);
                }
            }

            if (conditions != null)
            {
                foreach (var kvp in conditions)
                {
                    var condition = Expression.IfThen(
                        ExpressionEx.Not(kvp.Value.Item2),
                        Expression.Block(kvp.Value.Item1));
                    lines.Add(condition);
                }
            }

            return(lines.Count > 0 ? (Expression)Expression.Block(lines) : Expression.Empty());
        }
Пример #3
0
        protected override Expression CreateBlockExpression(Expression source, Expression destination, CompileArgument arg)
        {
            var mapped = base.CreateBlockExpression(source, destination, arg);

            //if source is not dict type, use ClassAdapter
            var srcDictType = arg.SourceType.GetDictionaryType();

            if (srcDictType == null || arg.Settings.IgnoreNonMapped == true)
            {
                return(mapped);
            }

            var keyType   = srcDictType.GetGenericArguments().First();
            var kvpType   = source.Type.ExtractCollectionType();
            var kvp       = Expression.Variable(kvpType, "kvp");
            var key       = Expression.Variable(keyType, "key");
            var keyAssign = Expression.Assign(key, Expression.Property(kvp, "Key"));

            //dest[kvp.Key] = convert(kvp.Value);
            var set = CreateSetFromKvp(kvp, key, destination, arg);

            if (arg.Settings.NameMatchingStrategy.SourceMemberNameConverter != NameMatchingStrategy.Identity)
            {
                set = Expression.Block(
                    Expression.Assign(
                        key,
                        Expression.Call(
                            MapsterHelper.GetConverterExpression(arg.Settings.NameMatchingStrategy.SourceMemberNameConverter),
                            "Invoke",
                            null,
                            key)),
                    set);
            }

            //ignore mapped
            var ignores = arg.Settings.Resolvers
                          .Select(r => r.SourceMemberName)
                          .Where(name => name != null)
                          .ToHashSet();

            //ignore
            var dict = new Dictionary <string, Expression>();

            foreach (var ignore in arg.Settings.Ignore)
            {
                if (ignore.Value.Condition == null)
                {
                    ignores.Add(ignore.Key);
                }
                else
                {
                    var body = ignore.Value.IsChildPath
                        ? ignore.Value.Condition.Body
                        : ignore.Value.Condition.Apply(arg.MapType, source, destination);
                    var setWithCondition = Expression.IfThen(
                        ExpressionEx.Not(body),
                        set);
                    dict.Add(ignore.Key, setWithCondition);
                }
            }

            //dict to switch
            if (dict.Count > 0 || ignores.Count > 0)
            {
                var cases = dict
                            .Select(k => Expression.SwitchCase(k.Value, Expression.Constant(k.Key)))
                            .ToList();
                if (ignores.Count > 0)
                {
                    cases.Add(Expression.SwitchCase(Expression.Empty(), ignores.Select(Expression.Constant)));
                }

                set = Expression.Switch(typeof(void), key, set, null, cases);
            }

            //if (kvp.Value != null)
            //  dest[kvp.Key] = convert(kvp.Value);
            var kvpValueType = kvpType.GetGenericArguments()[1];

            if (arg.Settings.IgnoreNullValues == true && kvpValueType.CanBeNull())
            {
                set = Expression.IfThen(
                    Expression.NotEqual(
                        Expression.Property(kvp, "Value"),
                        Expression.Constant(null, kvpValueType)),
                    set);
            }

            //foreach (var kvp in source) {
            //  dest[kvp.Key] = convert(kvp.Value);
            //}
            set = Expression.Block(new[] { key }, keyAssign, set);
            var loop = ExpressionEx.ForEach(source, kvp, set);

            return(mapped.NodeType == ExpressionType.Default
                ? loop
                : Expression.Block(mapped, loop));
        }
Пример #4
0
        protected override Expression CreateBlockExpression(Expression source, Expression destination, CompileArgument arg)
        {
            var dictArgs      = destination.Type.GetDictionaryType() !.GetGenericArguments();
            var shouldConvert = destination.Type.GetMethod("Add", dictArgs) == null;

            //var dict = (IDictionary<,>)dest;
            var actions = new List <Expression>();
            var dict    = destination;

            if (shouldConvert)
            {
                var dictType = typeof(IDictionary <,>).MakeGenericType(dictArgs);
                dict = Expression.Variable(dictType, "dict");
                actions.Add(ExpressionEx.Assign(dict, destination)); //convert to dict type
            }

            var mapped = base.CreateBlockExpression(source, dict, arg);

            if (mapped.NodeType != ExpressionType.Default)
            {
                actions.Add(mapped);
            }

            //if source is not dict type, use ClassAdapter only
            var srcDictType = arg.SourceType.GetDictionaryType();

            if (srcDictType == null || arg.Settings.IgnoreNonMapped == true)
            {
                return(shouldConvert && mapped.NodeType != ExpressionType.Default
                    ? Expression.Block(new[] { (ParameterExpression)dict }, actions)
                    : mapped);
            }

            //if (object.ReferenceEquals(source, destination))
            //  return destination;
            LabelTarget?label = null;

            if (source.Type.IsObjectReference() &&
                destination.Type.IsObjectReference() &&
                (source.Type.IsAssignableFrom(destination.Type) || destination.Type.IsAssignableFrom(source.Type)))
            {
                label = Expression.Label(arg.DestinationType);
                var refEquals = Expression.Call(typeof(object), nameof(ReferenceEquals), null, source, destination);
                actions.Add(Expression.IfThen(refEquals, Expression.Return(label, destination)));
            }

            var keyType   = srcDictType.GetGenericArguments().First();
            var kvpType   = source.Type.ExtractCollectionType();
            var kvp       = Expression.Variable(kvpType, "kvp");
            var key       = Expression.Variable(keyType, "key");
            var keyAssign = Expression.Assign(key, Expression.Property(kvp, "Key"));

            //dest[kvp.Key] = convert(kvp.Value);
            var set = CreateSetFromKvp(kvp, key, dict, arg);

            if (arg.Settings.NameMatchingStrategy.SourceMemberNameConverter != MapsterHelper.Identity)
            {
                set = Expression.Block(
                    Expression.Assign(
                        key,
                        Expression.Call(
                            ExpressionEx.GetNameConverterExpression(arg.Settings.NameMatchingStrategy.SourceMemberNameConverter),
                            "Invoke",
                            null,
                            key)),
                    set);
            }

            //ignore mapped
            var ignores = arg.Settings.Resolvers
                          .Select(r => r.SourceMemberName)
                          .Where(name => name != null)
                          .ToHashSet();

            //ignore
            var ignoreIfs = new Dictionary <string, Expression>();

            foreach (var ignore in arg.Settings.Ignore)
            {
                if (ignore.Value.Condition == null)
                {
                    ignores.Add(ignore.Key);
                }
                else
                {
                    var body = ignore.Value.IsChildPath
                        ? ignore.Value.Condition.Body
                        : ignore.Value.Condition.Apply(arg.MapType, source, dict);
                    var setWithCondition = Expression.IfThen(
                        ExpressionEx.Not(body),
                        set);
                    ignoreIfs.Add(ignore.Key, setWithCondition);
                }
            }

            //dict to switch
            if (ignoreIfs.Count > 0 || ignores.Count > 0)
            {
                var cases = ignoreIfs
                            .Select(k => Expression.SwitchCase(k.Value, Expression.Constant(k.Key)))
                            .ToList();
                if (ignores.Count > 0)
                {
                    cases.Add(Expression.SwitchCase(Expression.Empty(), ignores.Select(Expression.Constant)));
                }

                set = Expression.Switch(typeof(void), key, set, null, cases);
            }

            //if (kvp.Value != null)
            //  dest[kvp.Key] = convert(kvp.Value);
            var kvpValueType = kvpType.GetGenericArguments()[1];

            if (arg.Settings.IgnoreNullValues == true && kvpValueType.CanBeNull())
            {
                set = Expression.IfThen(
                    Expression.NotEqual(
                        Expression.Property(kvp, "Value"),
                        Expression.Constant(null, kvpValueType)),
                    set);
            }

            //foreach (var kvp in source) {
            //  dest[kvp.Key] = convert(kvp.Value);
            //}
            set = Expression.Block(new[] { key }, keyAssign, set);
            var loop = ExpressionEx.ForEach(source, kvp, set);

            actions.Add(loop);

            if (label != null)
            {
                actions.Add(Expression.Label(label, arg.DestinationType.CreateDefault()));
            }

            return(shouldConvert
                ? Expression.Block(new[] { (ParameterExpression)dict }, actions)
                : Expression.Block(actions));
        }