C#基于表达式(Expression)实现对象深拷贝

 使用方式如下,目标对象可以自己,也可以是其它对象:

 var copy = ObjectCopyByExpression.DeepCopy(pepole);

主要类:ObjectCopyByExpression

 public class ObjectCopyByExpression where TIn : class where TOut : class, new()
    {
        private static Func _DeepCopy = null;

        public static TOut DeepCopy(TIn tIn)
        {
            return _DeepCopy(tIn);
        }

        static ObjectCopyByExpression()
        {
            ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "TIn");
            Expression> expression = Expression.Lambda>(GetMemberInitExpression(typeof(TIn), typeof(TOut), parameterExpression), new ParameterExpression[] { parameterExpression });
            _DeepCopy = expression.Compile();
        }

        /// 
        /// 创建表达式
        /// 
        /// 
        /// 
        /// 
        /// 
        private static MemberInitExpression GetMemberInitExpression(Type inTypes, Type outTypes, Expression parameterExpression)
        {
            List memberBindings = new List();
            foreach (var outProperty in outTypes.GetProperties())
            {
                var inProperty = inTypes.GetProperty(outProperty.Name);
                if (inProperty != null && outProperty.CanRead)
                {
                    MemberExpression properTyMemberExpression = Expression.Property(parameterExpression, inProperty);

                    MemberBinding memberBinding = Expression.Bind(outProperty, IsObject(inProperty.PropertyType) ?
                        GetObjectBindingExpression(inProperty.PropertyType, outProperty.PropertyType, parameterExpression, properTyMemberExpression)
                        : properTyMemberExpression);
                    memberBindings.Add(memberBinding);
                }
            }

            foreach (var outFieldInfo in outTypes.GetFields())
            {
                var inField = inTypes.GetField(outFieldInfo.Name);
                if (inField != null)
                {
                    MemberExpression fieldMemberExpression = Expression.Field(parameterExpression, inField);

                    MemberBinding memberBinding = Expression.Bind(outFieldInfo, IsObject(outFieldInfo.FieldType) ?
                        GetObjectBindingExpression(inField.FieldType, outFieldInfo.FieldType, parameterExpression, fieldMemberExpression)
                        : fieldMemberExpression);
                    memberBindings.Add(memberBinding);
                }
            }

            MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(outTypes), memberBindings);
            return memberInitExpression;
        }

        /// 
        /// 判断是否为对象类型
        /// 
        /// 
        /// 
        private static bool IsObject(Type inTypes)
        {
            return !inTypes.IsValueType && inTypes.Name != "String";
        }

        /// 
        /// 获取对象赋值表达式
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        private static Expression GetObjectBindingExpression(Type inTypes, Type outTypes, Expression parameterExpression, MemberExpression memberExpression)
        {
            //字段 输入对象NULL时,对应的输出对像值
            ConstantExpression nullTinProperty = Expression.Constant(null, outTypes);
            ConstantExpression nullObeject = Expression.Constant(null, typeof(object));

            //比较,判断输入对象是否为 null
            BinaryExpression binaryExpression = Expression.Equal(memberExpression, nullObeject);

            //非null时,创建一个新对象
            MemberInitExpression subMemberInitExpression = GetMemberInitExpression(inTypes, outTypes, memberExpression);

            //if(tin.propertyinfo==null,null,new tin.propertyinfo{...})
            return Expression.Condition(binaryExpression, nullTinProperty, subMemberInitExpression);
        }
    }

已经知问题:

对象如果有自引用,会堆栈溢出

你可能感兴趣的:(c#,反射)