.Net Глубокое клонирование - каков наилучший способ сделать это? - PullRequest
11 голосов
/ 09 августа 2009

Мне нужно выполнить глубокое клонирование моей сложной объектной модели. Как вы думаете, что является лучшим способом сделать это в .Net?
Я думал о сериализации / десериализации
Нет необходимости упоминать, что MemberwiseClone недостаточно хорошо.

Ответы [ 7 ]

15 голосов
/ 09 августа 2009

Если вы управляете объектной моделью, вы можете написать код, чтобы сделать это, но это требует много обслуживания. Однако существует множество проблем, которые означают, что если вам не нужна абсолютно самая быстрая производительность, то сериализация часто является наиболее управляемым ответом.

Это один из случаев, когда BinaryFormatter работает приемлемо; обычно я не фанат (из-за проблем с версиями и т. д.), но поскольку сериализованные данные предназначены для немедленного использования, это не проблема.

Если вы хотите немного быстрее (но без собственного кода), тогда protobuf-net может помочь, но требует изменения кода (для добавления необходимых метаданных и т. Д.). И это на основе дерева (не на основе графа).

Другие сериализаторы (XmlSerializer, DataContractSerializer) также хороши, но если для клона это просто , они могут не предлагать намного больше BinaryFormatter (кроме, возможно, XmlSerializer не Т нужно [Serializable].

Так что на самом деле, это зависит от ваших конкретных классов и сценария.

9 голосов
/ 30 ноября 2009

Если вы выполняете код в среде с частичным доверием, такой как 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);
    }
}
5 голосов
/ 10 августа 2009

Пример глубокого клонирования из журнала 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));
    }
1 голос
/ 06 июня 2011

Пожалуйста, взгляните на действительно хорошую статью C # Object Clone Wars . Я нашел очень интересное решение там: Копируемый: платформа для копирования или клонирования .NET объектов

0 голосов
/ 01 ноября 2016

Лучший способ реализовать это вручную. Это будет действительно быстрее, чем любые другие общие методы. Также есть много библиотек для этой операции (Вы можете увидеть список с тестами производительности здесь ).

Кстати, BinaryFormatter очень медленно выполняет эту задачу и может быть полезен только для тестирования.

0 голосов
/ 10 августа 2009

Вы можете попробовать AltSerialize , который во многих случаях быстрее, чем сериализатор .Net. Он также обеспечивает кэширование и настраиваемые атрибуты для ускорения сериализации.

0 голосов
/ 09 августа 2009

Наилучшим способом, вероятно, является реализация интерфейса System.IClonable в вашем объекте и всех его полях, которые также требуют специальных возможностей глубокого клонирования. Затем вы реализуете метод Clone для возврата глубокой копии вашего объекта и его членов.

...