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