2013-05-05 70 views
9

來到protobuf網,真棒!我有一個關於空列表序列化的問題。Protobuf網空列表

我開始通過聲明我想要序列化對象:

[ProtoContract] 
class TestClass 
{ 
    [ProtoMember(1)] 
    List<int> _listOfInts = new List<int>(); 

    public TestClass() { } 

    public List<int> ListOfInts 
    { 
     get { return _listOfInts; } 
     set { _listOfInts = value; } 
    } 
} 

如果_listOfInts是空的(但不是null),當我deserialse這個對象永遠是零。這是有道理的看protobuf的約定,我目前解決此通過添加以下方法:

[ProtoAfterDeserialization] 
private void OnDeserialize() 
{ 
    if (_listOfInts == null) 
     _listOfInts = new List<int>(); 
} 

我的問題是我是否可以與附加attirbute將實現更簡潔時尚此相同的功能,有可能將空/空對象初始化爲空而不是空?

回答

5

如果您試圖防範空列表,您可以嘗試在屬性獲取器中進行延遲加載。

public List<int> ListOfInts 
{ 
    get { return _listOfInts ?? (_listOfInts = new List<int>()); } 
    set { _listOfInts = value; } 
} 

這樣你就可以讓串行器返回null。

+0

這是我沒有考慮過的可能性,如果可以的話,會投票給你。我仍然主要想知道是否有一個屬性可以爲我做到這一點。 – CanCan 2013-05-05 21:34:56

+0

您是否嘗試過[DefaultValue]屬性?不知道你是否可以初始化列表,但值得一試。 – Jras 2013-05-05 21:41:00

+0

@Jras我確實考慮過添加這樣的內容,但是每次看到它,事實上都會讓人們的代碼變得更糟,而不是更好 – 2013-05-06 00:06:44

6

在protobuf如何編碼數據方面存在一個基本問題:列表本身在數據中沒有出現 - 只是元素。正因爲如此,存儲關於列表的信息根本無處可見。可以通過使用條件序列化發送一個布爾值來欺騙它,但坦率地說這有點冒險和醜陋 - 並增加了複雜性。就我個人而言,我強烈建議從可能爲空的列表中抽象出來。例如:

private readonly List<Foo> items = new List<Foo>(); 
[ProtoMember(1)] 
public List<Foo> Items { get { return items; } } 

或者

private List<Foo> items; 
[ProtoMember(1)] 
public List<Foo> Items { get { return items ?? (items = new List<Foo>()); } } 

而且注意,這個建議不只是序列化:它是如何避免任意的空引用異常。人們通常不希望子集合爲空。

+0

是否有任何理由不在私人項目字段上初始化收集?我可以看到,如果你沒有訪問Items屬性的getter,那麼你不會掛在一個空的集合引用上,但是你每次都支付空值檢查的代價。它只是情景? – Shaun 2013-11-26 16:40:28