鉴于以下课程:
class A
{
public List<B> ListB;
// etc...
}
其中B
是另一个可以继承/包含其他类的类。
鉴于这种情况:
A
是一个大型类,包含许多引用类型B
标记为[Serializable]
,因为我无法访问B
以下执行深度复制的方法不起作用:
ICloneable
或MemberwiseClone
,因为类A
包含许多引用类型A
编写复制构造函数,因为该类很大且不断被添加到,并且包含无法深度复制的类(如B
)B
,其中没有可用的源代码)[Serializable]
如何深度复制课程A
?
答案 0 :(得分:8)
无论如何我都停止使用序列化进行深度复制,因为没有足够的控件(并非每个类都需要以相同的方式复制)。然后我开始实现自己的深层复制接口,并以应该复制的方式复制每个属性。
复制引用类型的典型方法:
示例:
class A
{
// copy constructor
public A(A copy) {}
}
// a referenced class implementing
class B : IDeepCopy
{
object Copy() { return new B(); }
}
class C : IDeepCopy
{
A A;
B B;
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();
}
}
你可能认为这是一项巨大的工作。但最后,它很简单直接,可以在需要的地方进行调整,并完全满足您的需求。
答案 1 :(得分:3)
你可以试试这个。它对我有用
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 article。
答案 2 :(得分:1)
private interface IDeepCopy<T> where T : class
{
T DeepCopy();
}
private class MyClass : IDeepCopy<MyClass>
{
public MyClass DeepCopy()
{
return (MyClass)this.MemberwiseClone();
}
}
Pluss: Yoy可以控制复制过程(如果您的类具有可以设置它们的标识符属性,或者您可以编写其他业务逻辑代码)
减:类可以标记为密封
答案 3 :(得分:0)
你不能这样做吗?
[Serializable]
class A
{
...
[NonSerialized]
public List<B> ListB;
....
}
然后参考How do you do a deep copy of an object in .NET (C# specifically)?获取克隆函数
答案 4 :(得分:0)
您的界面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(); }
}
答案 5 :(得分:-1)
来自使用json序列化的其他线程的answer是我见过的最好的。
public static T CloneJson<T>(this T source)
{
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source));
}
答案 6 :(得分:-1)
尝试使用内存流来获取对象的深层副本:
public static T MyDeepCopy<T>(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;
}
}