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; }
这样你就实现了深度拷贝