2009-08-09 20 views
10

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?

+4

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. –

+0

robi to bez serializacji http://valueinjecter.codeplex.com/wikipage?title=Deep%20Cloning&referringTitle=Home – Omu

+0

UltraMapper https://www.nuget.org/packages/UltraMapper/ – sam

Odpowiedz

0

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.

+2

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

+0

IClonable nie działa dla złożonych obiektów. –

13

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.

+0

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. –

0

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.

5

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)); 
    } 
8

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.

+0

Nie działa, gdy niektóre właściwości sklonowanego obiektu są interfejsami (np. IEnumerable, IList itp.). Zgłasza wyjątek. –

0

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.

Powiązane problemy