internal void FinishMap <TModel1, TModel2>(Dictionary <string, MemberBinding> bindings, HashSet <string> ignoreMembers) where TModel1 : class where TModel2 : class, new() { Type model2Type = typeof(TModel2); Type model1Type = typeof(TModel1); Dictionary <string, PropertyInfo> model1PiDic = model1Type.GetProperties().ToDictionary(pi => pi.Name, pi => pi); IEnumerable <PropertyInfo> model2Pis = model2Type.GetProperties().Where(pi => !bindings.ContainsKey(pi.Name) && !ignoreMembers.Contains(pi.Name) && model1PiDic.ContainsKey(pi.Name)); bindings.RemoveAllIfContains(ignoreMembers); var parameter = Expression.Parameter(model1Type, "model"); foreach (PropertyInfo member in model2Pis) { var memberExp = Expression.MakeMemberAccess(parameter, model1PiDic[member.Name]); Type model1MemberType = model1PiDic[member.Name].PropertyType; if (member.PropertyType == model1MemberType) { bindings.Add(member.Name, Expression.Bind(member, memberExp)); } else { //For Nullable Types if (Check.TryGetUnderlyingType(model1MemberType, out Type underlyingType)) { MethodInfo mi = typeof(Check).GetMethods().FirstOrDefault(p => p.Name == $"To{underlyingType.Name}"); if (mi != null) { var changeTypeExp = Expression.Call(mi, memberExp); bindings.Add(member.Name, Expression.Bind(member, changeTypeExp)); } else { throw new InvalidCastException($"Can't find the To{underlyingType} method from {typeof(Check).FullName} static class."); } } else { var valueExp = Expression.Convert(memberExp, member.PropertyType); bindings.Add(member.Name, Expression.Bind(member, valueExp)); } } } BindingsCasheProvider.Cashe <TModel1, TModel2>(bindings); NewExpression model = Expression.New(model2Type); MemberInitExpression memberInitExpression = Expression.MemberInit(model, bindings.Values); var exprBody = ExpressionVisitorFactory.AllParametersReplacer(parameter).Visit(memberInitExpression); var lambda = Expression.Lambda <Func <TModel1, TModel2> >(exprBody, parameter); CasheProvider <TModel1, TModel2> .SetMapper(lambda); }
public override Expression Visit(Expression node) { if (node.NodeType == ExpressionType.MemberAccess) { var memberExp = (MemberExpression)node; MemberAssignment member; if (_bindings.TryGetValue(memberExp.Member.Name, out member)) { var newMemberExp = ExpressionVisitorFactory.AllParametersReplacer(_newParamExp).Visit(member.Expression); return(base.Visit(newMemberExp)); } } return(base.Visit(node)); }
internal void FinishMergeMap <TModel1, TModel2>(Dictionary <string, MemberBinding> bindings, HashSet <string> ignoreMembers) where TModel1 : class where TModel2 : class, new() { Type model1Type = typeof(TModel2); Type model2Type = typeof(TModel1); var parameter1 = Expression.Parameter(model1Type, "model1"); var parameter2 = Expression.Parameter(model2Type, "model2"); foreach (var member in model1Type.GetProperties().Where(pi => !bindings.ContainsKey(pi.Name))) { var memberExp = Expression.MakeMemberAccess(parameter1, member); bindings.Add(member.Name, Expression.Bind(member, memberExp)); } NewExpression model = Expression.New(model1Type); MemberInitExpression memberInitExpression = Expression.MemberInit(model, bindings.Values); var exprBody = ExpressionVisitorFactory.AllParametersReplacer(parameter1, parameter2).Visit(memberInitExpression); var lambda = Expression.Lambda <Func <TModel1, TModel2, TModel2> >(exprBody, parameter2, parameter1); CasheProvider <TModel1, TModel2> .SetMapper(lambda); }