private static Expression?DictionaryFn(Expression source, IMemberModel destinationMember, CompileArgument arg) { var dictType = source.Type.GetDictionaryType(); if (dictType == null) { return(null); } var strategy = arg.Settings.NameMatchingStrategy; var destinationMemberName = destinationMember.GetMemberName(MemberSide.Destination, arg.Settings.GetMemberNames, strategy.DestinationMemberNameConverter); var key = Expression.Constant(destinationMemberName); var args = dictType.GetGenericArguments(); if (strategy.SourceMemberNameConverter != MapsterHelper.Identity) { var method = typeof(MapsterHelper).GetMethods() .First(m => m.Name == nameof(MapsterHelper.FlexibleGet) && m.GetParameters()[0].ParameterType.Name == dictType.Name) .MakeGenericMethod(args[1]); return(Expression.Call(method, source.To(dictType), key, ExpressionEx.GetNameConverterExpression(strategy.SourceMemberNameConverter))); } else { var method = typeof(MapsterHelper).GetMethods() .First(m => m.Name == nameof(MapsterHelper.GetValueOrDefault) && m.GetParameters()[0].ParameterType.Name == dictType.Name) .MakeGenericMethod(args); return(Expression.Call(method, source.To(dictType), key)); } }
private static Func <Expression, Expression, Expression, Expression> SetFunction(CompileArgument arg, Type dictType) { var strategy = arg.Settings.NameMatchingStrategy; if (arg.MapType == MapType.MapToTarget && strategy.DestinationMemberNameConverter != MapsterHelper.Identity) { var args = dictType.GetGenericArguments(); var setMethod = typeof(MapsterHelper).GetMethods() .First(m => m.Name == nameof(MapsterHelper.FlexibleSet)) .MakeGenericMethod(args[1]); var destNameConverter = ExpressionEx.GetNameConverterExpression(strategy.DestinationMemberNameConverter); return((dict, key, value) => Expression.Call(setMethod, dict, key, destNameConverter, value)); } else { var indexer = dictType.GetProperties().First(item => item.GetIndexParameters().Length > 0); return((dict, key, value) => Expression.Assign(Expression.Property(dict, indexer, key), value)); } }
private static Func <Expression, Expression, Expression> GetFunction(CompileArgument arg, Type dictType) { var strategy = arg.Settings.NameMatchingStrategy; var args = dictType.GetGenericArguments(); if (strategy.DestinationMemberNameConverter != MapsterHelper.Identity) { var getMethod = typeof(MapsterHelper).GetMethods() .First(m => m.Name == nameof(MapsterHelper.FlexibleGet) && m.GetParameters()[0].ParameterType.Name == dictType.Name) .MakeGenericMethod(args[1]); var destNameConverter = ExpressionEx.GetNameConverterExpression(strategy.DestinationMemberNameConverter); return((dict, key) => Expression.Call(getMethod, dict, key, destNameConverter)); } else { var getMethod = typeof(MapsterHelper).GetMethods() .First(m => m.Name == nameof(MapsterHelper.GetValueOrDefault) && m.GetParameters()[0].ParameterType.Name == dictType.Name) .MakeGenericMethod(args); return((dict, key) => Expression.Call(getMethod, dict, key)); } }
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)); }