2013-05-05 2 views
9

protobuf-netを介して来た、すばらしい!空リストのシリアライゼーションに関する質問があります。Protobuf-Netの空リスト

は私がシリアライズしたいオブジェクトを宣言することで起動します。

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

    public TestClass() { } 

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

私は、このオブジェクトは常にnullになりますですdeserialseとき_listOfIntsが空(ただし、nullではない)である場合

。これはいる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

+0

[DefaultValue]属性を試しましたか?あなたがリストを初期化できるかどうかは分かりませんが、試してみる価値があります。 – Jras

+0

@Jras私はそのような追加を検討しましたが、それを見るたびに、実際に人々のコードを悪化させるようになりました。 –

6

protobufがデータをどのようにエンコードするかという点で根本的な問題があります。リスト自体はデータ内にと表示されません。このため、リストに関する情報を保管するのは明らかではありません。条件付きシリアル化を使用してブール値を送信することで偽装することはできますが、それはちょっとハッキリで醜いです。個人的には、nullになる可能性のあるリストを抽象化することを強くお勧めします。たとえば、次のように

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

そして、このアドバイスはシリアライズについてだけではないことに注意してください:それは、任意のヌル参照例外を避けることについてです。通常、サブコレクションはnullになるとは考えていません。

+0

プライベートアイテムフィールドにコレクションを初期化しない理由はありますか? Itemsプロパティのgetterにアクセスしていない場合、空のコレクション参照にぶら下がっているのではなく、毎回nullチェックの代価を支払っていることがわかります。それはただの状況ですか? – Shaun