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

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

Ответ 1

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

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

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

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

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

Ответ 2

Если вы используете код в среде Partial Trust, такой как 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);
    }
}

Ответ 3

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

Ответ 5

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

Ответ 6

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

Ответ 7

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

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