如何深度复制类而不将其标记为Serializable

鉴于以下课程:

class A { public List ListB; // etc... } 

其中B是另一个可以inheritance/包含其他类的类。


鉴于这种情况:

  1. A是一个大类,包含许多引用类型
  2. 我不能将B标记为[Serializable]因为我无法访问B源代码

以下执行深度复制的方法不起作用:

  1. 我不能使用ICloneableMemberwiseClone因为A类包含许多引用类型
  2. 我无法为A编写复制构造函数,因为该类很大且不断被添加到,并且包含无法深度复制的类(如B
  3. 我无法使用序列化,因为我无法将包含的类(如B ,没有可用的源代码)标记为[Serializable]

我怎样才能深造A级?

我无论如何都停止使用序列化进行深度复制,因为没有足够的控制(不是每个类都需要以相同的方式复制)。 然后我开始实现自己的深层复制接口,并以应该复制的方式复制每个属性。

复制引用类型的典型方法:

  • 使用复制构造函数
  • 使用工厂方法(例如,不可变类型)
  • 用你自己的“克隆”
  • 仅复制引用(例如,其他根类型)
  • 创建新实例和复制属性(例如,自己编写的类型缺少复制构造函数)

例:

 class A { // copy constructor public A(A copy) {} } // a referenced class implementing class B : IDeepCopy { object Copy() { return new B(); } } class C : IDeepCopy { AA; BB; object Copy() { C copy = new C(); // copy property by property in a appropriate way copy.A = new A(this.A); copy.B = this.B.Copy(); } } 

你可能认为这是一项巨大的工作。 但最后,它很简单直接,可以在需要的地方进行调整,并完全满足您的需求。

你可以试试这个。 这个对我有用

  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"); } 

感谢DetoX83关于代码项目的文章 。

  private interface IDeepCopy where T : class { T DeepCopy(); } private class MyClass : IDeepCopy { public MyClass DeepCopy() { return (MyClass)this.MemberwiseClone(); } } 

Pluss: Yoy可以控制复制过程(如果你的类有标识符属性你可以设置它们,或者你可以编写其他业务逻辑代码)


减:课程可以标记为密封


你不能这样做吗?

 [Serializable] class A { ... [NonSerialized] public List ListB; .... } 

然后参考如何在.NET中对对象执行深层复制(特别是C#)? 用于克隆function

你的界面IDeepCopy正是ICloneable指定的。

 class B : ICloneable { public object Clone() { return new B(); } } 

以及更友好的实施:

 class B : ICloneable { public B Clone() { return new B(); } // explicit implementation of ICloneable object ICloneable.Clone() { return this.Clone(); } } 

尝试使用内存流来获取对象的深层副本:

  public static T MyDeepCopy(this T source) { try { //Throw if passed object has nothing if (source == null) { throw new Exception("Null Object cannot be cloned"); } // Don't serialize a null object, simply return the default for that object if (Object.ReferenceEquals(source, null)) { return default(T); } //variable declaration T copy; var obj = new DataContractSerializer(typeof(T)); using (var memStream = new MemoryStream()) { obj.WriteObject(memStream, source); memStream.Seek(0, SeekOrigin.Begin); copy = (T)obj.ReadObject(memStream); } return copy; } catch (Exception) { throw; } } 

这是更多。

使用json序列化的另一个线程的答案是我见过的最好的。

 public static T CloneJson(this T source) { if (Object.ReferenceEquals(source, null)) { return default(T); } return JsonConvert.DeserializeObject(JsonConvert.SerializeObject(source)); }