2012-08-15 20 views
5

Bối cảnh: điều này dựa trên câu hỏi đã được hỏi và sau đó bị xóa trước khi tôi có thể trả lời - nhưng tôi nghĩ đó là một câu hỏi hay, vì vậy tôi đã dọn dẹp nó, lặp lại nó và đăng lại nó.Tôi có thể sử dụng lại các cá thể đối tượng để tránh phân bổ với protobuf-net không?

Trong trường hợp thông lượng cao sử dụng protobuf-net, trong đó rất nhiều phân bổ là một vấn đề (đặc biệt cho GC), có thể tái sử dụng các đối tượng không? Ví dụ: bằng cách thêm phương thức Clear()?

[ProtoContract] 
public class MyDTO 
{ 
    [ProtoMember(1)] 
    public int Foo { get; set; } 
    [ProtoMember(2)] 
    public string Bar { get; set; } 
    [ProtoMember(3, DataFormat = DataFormat.Group)] 
    public List<int> Values { get { return values; } } 
    private readonly List<int> values = new List<int>(); 

    public void Clear() 
    { 
     values.Clear(); 
     Foo = 0; 
     Bar = null; 
    } 
} 

Trả lời

6

protobuf-net sẽ không bao giờ gọi phương thức riêng của mình Clear() của bạn, nhưng đối với các trường hợp đơn giản bạn chỉ có thể làm điều này cho mình, và sử dụng phương pháp Merge (trên API v1, hoặc chỉ cần vượt qua các đối tượng vào Deserialize trong v2 API). Ví dụ:

MyDTO obj = new MyDTO(); 
for(...) { 
    obj.Clear(); 
    Serializer.Merge(obj, source);   
} 

này nạp dữ liệu vào hiệnobj thay vì tạo ra một đối tượng mới mỗi lần.

Trong trường hợp phức tạp hơn, nơi bạn muốn giảm số lượng phân bổ đối tượng, và vui lòng xử lý đối tượng gộp/tái sử dụng chính mình, thì bạn có thể sử dụng nhà máy tùy chỉnh. Ví dụ, bạn có thể thêm một phương pháp để MyDTO như:

// this can also accept serialization-context parameters if 
// you want to pass your pool in, etc 
public static MyDTO Create() 
{ 
    // try to get from the pool; only allocate new obj if necessary 
    return SomePool.GetMyDTO() ?? new MyDTO(); 
} 

và, ít ứng dụng khởi động, cấu hình protobuf-net để biết về nó:

RuntimeTypeModel.Default[typeof(MyDTO)].SetFactory("Create"); 

(SetFactory cũng có thể chấp nhận một MethodInfo - hữu ích nếu phương pháp nhà máy không được khai báo bên trong loại đang được đề cập)

Với điều này, điều gì sẽ xảy ra là phương pháp nhà máy được sử dụng thay vì cách xây dựng thông thường cơ chế. Nó vẫn còn, tuy nhiên, hoàn toàn công việc của bạn để làm sạch (Clear()) các đối tượng khi bạn đã kết thúc với họ, và để trả lại chúng vào hồ bơi của bạn. Điều đặc biệt tốt đẹp về cách tiếp cận nhà máy là nó sẽ làm việc cho các mục con mới trong danh sách, vv, mà bạn không thể làm chỉ từ Merge.

+0

Xin chào Marc, điều gì xảy ra nếu tôi không triển khai phương thức Clear()? Tất cả các trường có bị ghi đè không? – driAn

+1

@driAn chỉ các trường có dữ liệu trong luồng trong nước mới được chỉ định. Nếu bạn sử dụng một nhà máy tùy chỉnh tái chế các trường hợp, bạn nên cung cấp mã đặt lại của riêng bạn bên trong nhà máy. Nếu bạn không sử dụng một nhà máy tùy chỉnh, đây không phải là vấn đề –

+0

Xin chào Marc, tôi đang tìm phương pháp Deserialize() đã nói ở trên với cá thể đối tượng để điền/hợp nhất. Nhưng tôi đã không tìm thấy nó. Tôi chỉ tìm thấy một phương pháp: Serializer.Deserialize (Stream). Vẫn còn cách để xác định cá thể đối tượng cần điền không? Tôi muốn sử dụng lại các đối tượng từ một nhóm đối tượng và cách đó dường như dễ dàng hơn để đối phó với cách khác với một nhà máy tùy chỉnh ... Cảm ơn trước. –

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