C# 使用表达式树复制属性值,转化为指定类型 ExpressionTree CopyProperties
之前使用的是网上的一个表达式树版本,使用时需要显示写出参数及返回值的类型 Tin TOut, 略显麻烦
public static class TransExpV2{ private static readonly Func Func = GetFunc(); private static Func GetFunc() { Type inType = typeof(TIn); Type outType = typeof(TOut); ParameterExpression parameterExpression = Expression.Parameter(inType, "inParam"); List memberBindingList = new List (); PropertyInfo[] inProperties = inType.GetProperties(); PropertyInfo[] outProperties = outType.GetProperties(); foreach (var inProp in inProperties) { foreach (var outProp in outProperties) { if (inProp.Name == outProp.Name) { if (outProp.CanWrite) { MemberExpression property = Expression.Property(parameterExpression, inProp); MemberBinding memberBinding = Expression.Bind(outProp, property); memberBindingList.Add(memberBinding); } break; } } } MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(outType), memberBindingList.ToArray()); Expression > lambda = Expression.Lambda >(memberInitExpression, new ParameterExpression[] { parameterExpression }); return lambda.Compile(); } public static TOut Trans(TIn tIn) { return Func(tIn); } }
经过一点研究,决定还是使用另外一种使用缓存的版本,只用指定返回类型即可。效率比上面的代码略低,但比普通的反射还是要快不少。
静态类中声明以下方法及即可
static DictionarydicMappedFunc = new Dictionary (); public static T ToMapped (this object instance) { if (instance == null) throw new ArgumentNullException(); Type instanceType = instance.GetType(); Type toType = typeof(T); string key = $"{instanceType.FullName}-{toType.FullName}"; if (!dicMappedFunc.ContainsKey(key)) { ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "instance"); List memberBindingList = new List (); PropertyInfo[] instanceProps = instanceType.GetCacheProperties(); PropertyInfo[] toProps = toType.GetCacheProperties(); foreach (PropertyInfo insProp in instanceProps) { foreach (PropertyInfo toProp in toProps) { if (insProp.Name == toProp.Name) { if (toProp.CanWrite) { MemberExpression property = Expression.Property(Expression.Convert(parameterExpression, instanceType), insProp); MemberBinding memberBinding = Expression.Bind(toProp, property); memberBindingList.Add(memberBinding); } break; } } } MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(toType), memberBindingList.ToArray()); Expression > lambda = Expression.Lambda >(memberInitExpression, new ParameterExpression[] { parameterExpression }); Func
使用时复制相同属性名的属性值,数据类型需相同