• C# 使用表达式树复制属性值,转化为指定类型 ExpressionTree CopyProperties


    之前使用的是网上的一个表达式树版本,使用时需要显示写出参数及返回值的类型 Tin TOut, 略显麻烦

        public static class TransExpV2<TIn, TOut>
        {
            private static readonly Func<TIn, TOut> Func = GetFunc();
            private static Func<TIn, TOut> GetFunc()
            {
                Type inType = typeof(TIn);
                Type outType = typeof(TOut);
    
                ParameterExpression parameterExpression = Expression.Parameter(inType, "inParam");
                List<MemberBinding> memberBindingList = new List<MemberBinding>();
    
                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<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[] { parameterExpression });
                return lambda.Compile();
            }
    
            public static TOut Trans(TIn tIn)
            {
                return Func(tIn);
            }
        }

    经过一点研究,决定还是使用另外一种使用缓存的版本,只用指定返回类型即可。效率比上面的代码略低,但比普通的反射还是要快不少。

    静态类中声明以下方法及即可

            static Dictionary<string, object> dicMappedFunc = new Dictionary<string, object>();
    
            public static T ToMapped<T>(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<MemberBinding> memberBindingList = new List<MemberBinding>();
    
                    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<Func<object, T>> lambda = Expression.Lambda<Func<object, T>>(memberInitExpression, new ParameterExpression[] { parameterExpression });
    
                    Func<object, T> func = lambda.Compile();
                    dicMappedFunc[key] = func;
                }
    
                var function = (Func<object, T>)dicMappedFunc[key];
    
                return function(instance);
            }
    

    使用时复制相同属性名的属性值,数据类型需相同

  • 相关阅读:
    Corn Fields
    状压DP
    全排列函数
    搜索
    前缀和与差分
    最小花费
    【Lintcode】062.Search in Rotated Sorted Array
    【LeetCode】039. Combination Sum
    【LeetCode】040. Combination Sum II
    【LeetCode】047. Permutations II
  • 原文地址:https://www.cnblogs.com/xyz0835/p/10961317.html
Copyright © 2020-2023  润新知