C# DeepClone 深拷贝

常规利用反射进行克隆

   public static T CloneModel<T>(T oModel)
    {
        var oRes = default(T);
        var oType = typeof(T);

        //create new obj
        oRes = (T)Activator.CreateInstance(oType);

        //pass 1 property
        var lstPro = oType.GetProperties();
        foreach (var oPro in lstPro)
        {
            var oValue = oPro.GetValue(oModel,null);
            oPro.SetValue(oRes, oValue, null);
        }

        var lstField = oType.GetFields();
        foreach (var oField in lstField)
        {
            var oValue = oField.GetValue(oModel);
            oField.SetValue(oRes, oValue);
        }
        return oRes;
    }

但是当你克隆的字段中有引用类型的时候并不能真正的拷贝出一个新的如list 

因此在SetValue的时候 你需要进行深度拷贝

代码如下可直接使用

public static object DeepCopy(object obj)
    {
        if (obj == null)
            return null;
        Type type = obj.GetType();

        if (type.IsValueType || type == typeof(string))
        {
            return obj;
        }
        else if (type.IsArray)
        {
            Type elementType = Type.GetType(
                 type.FullName.Replace("[]", string.Empty));
            var array = obj as Array;
            Array copied = Array.CreateInstance(elementType, array.Length);
            for (int i = 0; i < array.Length; i++)
            {
                copied.SetValue(DeepCopy(array.GetValue(i)), i);
            }
            return Convert.ChangeType(copied, obj.GetType());
        }
        else if (type.IsClass)
        {

            object toret = Activator.CreateInstance(obj.GetType());
            FieldInfo[] fields = type.GetFields(BindingFlags.Public |
                        BindingFlags.NonPublic | BindingFlags.Instance);
            foreach (FieldInfo field in fields)
            {
                object fieldValue = field.GetValue(obj);
                if (fieldValue == null)
                    continue;
                field.SetValue(toret, DeepCopy(fieldValue));
            }
            return toret;
        }
        else
            throw new ArgumentException("Unknown type");
    }

使用的话就是在SetValue时 的oValue进行DeepClone即可

 public static T CloneModel<T>(T oModel)
    {
        var oRes = default(T);
        var oType = typeof(T);

        //create new obj
        oRes = (T)Activator.CreateInstance(oType);

        //pass 1 property
        var lstPro = oType.GetProperties();
        foreach (var oPro in lstPro)
        {
            var oValue = oPro.GetValue(oModel,null);
            oPro.SetValue(oRes, DeepCopy(oValue), null);
        }

        var lstField = oType.GetFields();
        foreach (var oField in lstField)
        {
            var oValue = oField.GetValue(oModel);
            oField.SetValue(oRes, DeepCopy(oValue));
        }
        return oRes;
    }

这样你就实现了深度拷贝

posted @ 2017-12-07 17:58  叫我张先生  阅读(1667)  评论(0编辑  收藏  举报