2009-08-09 24 views
10

Tôi cần phải thực hiện nhân bản sâu trên mô hình đối tượng phức tạp của mình. Bạn nghĩ gì là cách tốt nhất để làm điều đó trong .Net?
Tôi nghĩ về việc sắp xếp/Deserializing
không cần phải đề cập rằng MemberwiseClone là không đủ tốt.. Net Nhân bản sâu - cách tốt nhất để làm điều đó là gì?

+4

Hãy thực sự cẩn thận; đây có phải là điều bạn thực sự muốn nói không? Thông tư tham chiếu giữa các đối tượng có thể nhanh chóng gây ra các vấn đề với nhân bản sâu. –

+0

điều này thực hiện mà không cần serialization http://valueinjecter.codeplex.com/wikipage?title=Deep%20Cloning&referringTitle=Home – Omu

+0

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

Trả lời

0

Cách tốt nhất có thể là triển khai giao diện System.IClonable trong đối tượng của bạn và tất cả các trường của nó cũng cần các khả năng nhân bản sâu tùy chỉnh. Sau đó, bạn triển khai phương thức Clone để trả về bản sao sâu của đối tượng và thành viên của đối tượng.

+2

Vẫn còn các đề xuất chống lại điều này và Tôi đồng ý với họ.IClonable trên một đối tượng có thể có nghĩa là sâu, trong khi trên một đối tượng khác là nông cạn. Không có cách nào để phân biệt khi thực hiện cuộc gọi. Tất nhiên, điều này thực sự không hoàn toàn áp dụng cho một dự án nội bộ, nhưng không phải là một thực tế tồi để nhận ra sớm. – jfsk3

+0

IClonable không hoạt động đối với các đối tượng phức tạp. –

13

Nếu bạn kiểm soát mô hình đối tượng, sau đó bạn có thể viết mã để làm điều đó, nhưng nó là rất nhiều bảo trì. Tuy nhiên, có rất nhiều vấn đề, có nghĩa là trừ khi bạn cần hoàn toàn hiệu suất nhanh nhất, sau đó việc tuần tự hóa thường là câu trả lời dễ quản lý nhất.

Đây là một trong những trường hợp mà BinaryFormatter hoạt động được chấp nhận; bình thường tôi không phải là một fan (do các vấn đề với versioning, vv) - nhưng vì dữ liệu tuần tự là để tiêu thụ ngay lập tức, đây không phải là vấn đề.

Nếu bạn muốn nhanh hơn một chút (nhưng không có mã của riêng bạn), thì protobuf-net có thể hữu ích, nhưng yêu cầu thay đổi mã (để thêm siêu dữ liệu cần thiết, v.v.). Và nó là dựa trên cây (không dựa trên đồ thị).

serializers Khác (XmlSerializer, DataContractSerializer) cũng là tốt, nhưng nếu nó là chỉ cho clone, họ có thể không cung cấp nhiều hơn BinaryFormatter (ngoại trừ có lẽ rằng XmlSerializer không cần [Serializable].

Vì vậy, thực sự, nó phụ thuộc vào các lớp học chính xác của bạn và kịch bản.

+0

Có lẽ một liên kết đến ví dụ có thể là tốt đẹp. Im sử dụng UWP và tôi không thể sử dụng BinaryFormatter. Trình tuần tự hóa XML được đưa ra dưới đây bởi Marty. Tôi tò mò về DataContractSerializer và protobuf-net. –

0

bạn có thể thử AltSerialize mà trong nhiều trường hợp là nhanh hơn so với serializer Net. nó cũng cung cấp bộ nhớ đệm và tùy chỉnh các thuộc tính để tăng tốc độ tuần tự.

5

Ví dụ về nhân bản sâu sắc từ tạp chí 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

Nếu bạn đang chạy mã trong một môi trường tin cậy phần như Rackspace đám mây, bạn sẽ có khả năng bị hạn chế từ việc sử dụng BinaryFormatter. XmlSerializer có thể được sử dụng thay thế.

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); 
    } 
} 
+0

Không hoạt động khi một số thuộc tính của đối tượng nhân bản là giao diện (ví dụ: IEnumerable, IList, v.v.). Ném một ngoại lệ. –

0

Cách tốt nhất để thực hiện thủ công điều này. Nó sẽ thực sự nhanh hơn bất kỳ phương pháp chung nào khác. Ngoài ra, có rất nhiều thư viện cho hoạt động này (Bạn có thể thấy một số danh sách với các tiêu chí hiệu suất here).

Nhân tiện, BinaryFormatter rất chậm cho tác vụ này và chỉ có thể tốt để thử nghiệm.

Các vấn đề liên quan