.Net深度克隆 - 最好的方法是什么?

时间:2009-08-09 12:17:04

标签: c# .net clone

我需要在我的复杂对象模型上执行深度克隆。您认为在.Net中做到这一点的最佳方式是什么? 我想过序列化/反序列化 无需提及MemberwiseClone不够好。

7 个答案:

答案 0 :(得分:15)

如果您控制对象模型,那么您可以编写代码来执行此操作,但这需要大量维护。但是,有很多问题,这意味着除非您需要绝对最快的性能,否则序列化通常是最易于管理的答案。

这是BinaryFormatter可以接受的情况之一;通常我不是粉丝(由于版本控制等问题) - 但由于序列化数据是立即消费的,所以这不是问题。

如果你想要它快一点(但没有你自己的代码),那么protobuf-net可能会有所帮助,但需要更改代码(添加必要的元数据等)。它是基于树的(不是基于图形的)。

其他序列化程序(XmlSerializerDataContractSerializer)也没问题,但如果它只是 克隆,它们可能不会提供超过BinaryFormatter(除了XmlSerializer也许[Serializable]不需要{{1}}。

所以真的,这取决于你的确切类和场景。

答案 1 :(得分:9)

如果您在部分信任环境(如Rackspace Cloud)中运行代码,则可能会限制使用BinaryFormatter。可以改为使用XmlSerializer。

public static T DeepClone<T>(T obj)
{
    using (var ms = new MemoryStream())
    {
        XmlSerializer xs = new XmlSerializer(typeof(T));
        xs.Serialize(ms, obj);
        ms.Position = 0;

        return (T)xs.Deserialize(ms);
    }
}

答案 2 :(得分:5)

msdn杂志的深度克隆示例:

    Object DeepClone(Object original)
    {
        // Construct a temporary memory stream
        MemoryStream stream = new MemoryStream();

        // Construct a serialization formatter that does all the hard work
        BinaryFormatter formatter = new BinaryFormatter();

        // This line is explained in the "Streaming Contexts" section
        formatter.Context = new StreamingContext(StreamingContextStates.Clone);

        // Serialize the object graph into the memory stream
        formatter.Serialize(stream, original);

        // Seek back to the start of the memory stream before deserializing
        stream.Position = 0;

        // Deserialize the graph into a new set of objects
        // and return the root of the graph (deep copy) to the caller
        return (formatter.Deserialize(stream));
    }

答案 3 :(得分:1)

请看一下非常好的文章C# Object Clone Wars。我在那里找到了一个非常有趣的解决方案:Copyable: A framework for copying or cloning .NET objects

答案 4 :(得分:0)

最好的方法可能是在对象及其所有需要自定义深度克隆功能的字段中实现System.IClonable接口。然后,您实现Clone方法以返回对象及其成员的深层副本。

答案 5 :(得分:0)

您可以尝试AltSerialize,在许多情况下,它比.Net序列化程序更快。它还提供缓存和自定义属性以加速序列化。

答案 6 :(得分:0)

手动实施此方法的最佳方式。它将比任何其他通用方法更快。此外,还有很多用于此操作的库(您可以看到一些包含性能基准的列表here)。

顺便说一下,BinaryFormatter对于这项任务来说非常慢,并且只能用于测试。