【发布时间】:2011-04-08 12:05:53
【问题描述】:
我想制作一个对象的深层副本,这样我就可以更改新副本,并且仍然可以选择取消我的更改并取回原始对象。
我的问题是对象可以是任何类型,甚至来自未知程序集。
我不能使用BinaryFormatter 或XmlSerializer,因为对象不必要地具有[Serializable] 属性。
我曾尝试使用Object.MemberwiseClone() 方法来做到这一点:
public object DeepCopy(object obj)
{
var memberwiseClone = typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic);
var newCopy = memberwiseClone.Invoke(obj, new object[0]);
foreach (var field in newCopy.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
{
if (!field.FieldType.IsPrimitive && field.FieldType != typeof(string))
{
var fieldCopy = DeepCopy(field.GetValue(newCopy));
field.SetValue(newCopy, fieldCopy);
}
}
return newCopy;
}
问题在于它不适用于可枚举(数组、列表等),不适用于字典。
那么,如何在 C# 中制作未知对象的深层副本?
TNX 很多!
【问题讨论】:
-
在任意对象上调用
MemberwiseClone是邪恶的。 -
我在数组和字典上试过这个,它们似乎都可以工作。我在开头添加了一个空检查。这似乎是基本对象的通用解决方案。正如 Slaks 提到的,它对于文件流来说不是一个好主意,例如它将相同的句柄复制到文件流。它们都将依赖于流的关闭或搜索。如果您知道它并不总是深度克隆,那么它是一个有趣的解决方案。
-
我还阅读了一个解决方案,您可以在其中检查 ICloneable 接口。如果实现了 ICloneable,则调用它,否则只需创建一个空实例。
-
我认为它没有完全理解我想要做什么。我正在尝试创建一个 DEEP 副本,这意味着复制对象在属性等中包含的所有对象层次结构。因此,我显示的方法不适用于类数组,只需尝试更改其中一个类,然后你会发现“复制”数组中的值也发生了变化。我希望数组(或任何对象)完全独立,因此更改源对象中的值不会更改我创建的副本。
-
我们了解您想要做什么。然而,深度复制任意对象完全不可能。