Muszę wykonać głębokie klonowanie mojego złożonego modelu obiektu. Jak myślisz, co jest najlepszym sposobem na to w .Net?
Myślałem o serializowaniu/Deserializowaniu
nie trzeba wspominać, że MemberwiseClone
nie jest wystarczająco dobre..Net Głębokie klonowanie - jaki jest najlepszy sposób na zrobienie tego?
Odpowiedz
Najlepszym sposobem jest prawdopodobnie wdrożenie interfejsu System.IClonable w obiekcie i we wszystkich jego polach, które również wymagają niestandardowych funkcji głębokiego klonowania. Następnie zaimplementuj metodę Clone, aby zwrócić głęboką kopię obiektu i jego członków.
Nadal istnieją zalecenia przeciw temu i Zgadzam się z nimi.ICONowalne na jednym obiekcie może oznaczać głębokie, podczas gdy na innym jest płytkie. Nie ma sposobu, aby rozróżnić podczas wykonywania połączenia. Oczywiście nie jest to całkowicie możliwe do zastosowania w projekcie wewnętrznym, ale nie jest to zła praktyka, którą należy wcześnie rozpoznać. – jfsk3
IClonable nie działa dla złożonych obiektów. –
Jeśli kontrolujesz model obiektu, możesz napisać kod, aby to zrobić, ale wymaga to wielu czynności konserwacyjnych. Istnieje jednak wiele problemów, które oznaczają, że chyba najbardziej potrzebna jest maksymalna wydajność, a następnie serializacja jest często najłatwiejszą do rozwiązania odpowiedzią.
Jest to jeden z przypadków, w których BinaryFormatter
działa akceptowalnie; zwykle nie jestem fanem (ze względu na problemy z wersjonowaniem itp.) - ale ponieważ zserializowane dane są przeznaczone do natychmiastowej konsumpcji, nie jest to problemem.
Jeśli chcesz go nieco szybciej (ale bez własnego kodu), to może pomóc protobuf-net
, ale wymaga zmian kodu (aby dodać niezbędne metadane itp.). Jest oparty na drzewach (nie na grafach).
Inne serializers (XmlSerializer
, DataContractSerializer
) także są w porządku, ale jeśli jest tylko dla klonu, mogą one nie oferują znacznie ponad BinaryFormatter
(może z wyjątkiem tego XmlSerializer
nie potrzebuje [Serializable]
.
Tak naprawdę, to zależy od dokładnych klas i scenariusza.
Być może link do przykładu może być miły. Im przy użyciu UWP i nie mogę używać BinaryFormatter. Serializator XML jest podany poniżej przez Marty'ego. Interesuje mnie DataContractSerializer i protobuf-net. –
można spróbować AltSerialize co w wielu przypadkach jest szybszy niż serializatora .NET. zapewnia również buforowanie i atrybutów niestandardowych, aby przyspieszyć serializacji.
Przykład głębokim klonowanie z magazynu 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));
}
Jeśli używasz kodu w częściowym środowiska Powierniczego takich jak Rackspace Cloud, będzie prawdopodobnie ograniczony z użyciem BinaryFormatter. Zamiast tego można użyć XmlSerializer.
Nie działa, gdy niektóre właściwości sklonowanego obiektu są interfejsami (np. IEnumerable, IList itp.). Zgłasza wyjątek. –
Proszę spojrzeć na naprawdę dobry artykuł C# Object Clone Wars. Znalazłem tam bardzo interesujące rozwiązanie: Copyable: A framework for copying or cloning .NET objects
Najlepszym sposobem na wdrożenie tego ręcznie. Będzie to naprawdę szybsze niż jakiekolwiek inne ogólne metody. Ponadto istnieje wiele bibliotek dla tej operacji (możesz zobaczyć listę z testami wydajności here).
Nawiasem mówiąc, BinaryFormatter jest bardzo powolny dla tego zadania i może być dobry tylko do testowania.
Bądź naprawdę ostrożny; czy to naprawdę masz na myśli? Okrężne odniesienia między obiektami mogą szybko powodować problemy z głębokim klonowaniem. –
robi to bez serializacji http://valueinjecter.codeplex.com/wikipage?title=Deep%20Cloning&referringTitle=Home – Omu
UltraMapper https://www.nuget.org/packages/UltraMapper/ – sam