Мне нужно выполнить глубокое клонирование моей сложной объектной модели. Как вы думаете, лучший способ сделать это в .Net?
Я думал о сериализации/десериализации
не нужно упоминать, что MemberwiseClone
недостаточно хорош.
.Net Глубокое клонирование - что лучший способ сделать это?
Ответ 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));
}
Ответ 4
Пожалуйста, взгляните на действительно хорошую статью С# Object Clone Wars. Я нашел там очень интересное решение: Скопируемый: структура для копирования или клонирования объектов .NET
Ответ 5
Лучшим способом, вероятно, является внедрение интерфейса System.IClonable в ваш объект и все его поля, которые также нуждаются в пользовательских возможностях глубокого клонирования. Затем вы реализуете метод Clone, чтобы вернуть глубокую копию вашего объекта и его членов.
Ответ 6
Вы можете попробовать AltSerialize, который во многих случаях быстрее, чем сериализатор .Net. Он также обеспечивает кэширование и пользовательские атрибуты для ускорения сериализации.
Ответ 7
Лучший способ реализовать это вручную. Это будет действительно быстрее, чем любые другие общие методы. Кроме того, для этой операции существует много библиотек (вы можете увидеть список с показателями производительности здесь).
Кстати, BinaryFormatter очень медленный для этой задачи и может быть хорошим только для тестирования.