2013-05-05 5 views
9

Kam über Protobuf-Net, genial! Ich habe eine Frage bezüglich der Serialisierung von leeren Listen.Protobuf-Net Empty Liste

Ich beginne, indem das Objekt deklarieren ich serialisieren möchten:

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

    public TestClass() { } 

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

Wenn _listOfInts leer ist (aber nicht null), wenn ich das Objekt deserialse wird immer null sein. Dies macht Sinn, an der protobuf Konvention suchen, und ich arbeite zur Zeit um den durch die folgende Methode hinzu:

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

Meine Frage ist, ob ich die gleiche Funktionalität in einer prägnanten Art und Weise erreicht werden kann, möglicherweise mit einem zusätzlich attirbute die Initialisieren Sie leere/leere Objekte als leer statt als null?

Antwort

5

Wenn Sie versuchen, sich vor einer Null-Liste zu schützen, können Sie versuchen, das Lazy-Laden im Eigenschaften-Getter durchzuführen.

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

Auf diese Weise können Sie einfach zulassen, dass der Serializer null zurückgibt.

+0

Dies ist eine Möglichkeit, die ich nicht in Betracht gezogen hätte, würde Sie abstimmen, wenn ich könnte. Ich bin immer noch primär interessiert zu wissen, ob es ein Attribut gibt, das das für mich tun würde. – CanCan

+0

Haben Sie das Attribut [DefaultValue] versucht? Nicht sicher, ob Sie Listen initialisieren könnten, aber einen Versuch wert. – Jras

+0

@Jras Ich habe darüber nachgedacht, solche hinzuzufügen, aber jedes Mal, wenn ich es angeschaut habe, stellt sich heraus, dass der Code der Leute schlimmer wird, nicht besser –

6

Es gibt ein grundlegendes Problem hier in Bezug darauf, wie Protobuf Daten codiert: die Liste selbst erscheint nicht in den Daten - nur die Elemente. Aus diesem Grund ist es nirgendwo offensichtlich, Informationen über die Liste zu speichern. Es kann gefälscht werden, indem man einen Boolean mit bedingter Serialisierung sendet, aber ehrlich gesagt ist das ein bisschen hacky und hässlich - und fügt Komplexität hinzu. Persönlich rate ich dringend davon ab, von Listen, die jemals null sein könnten, zu abstrahieren. Zum Beispiel:

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

Oder

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

Und beachten Sie, dass dieser Rat nicht nur um die Serialisierung ist: Es geht um beliebige Null-Referenz-Ausnahmen zu vermeiden. Personen erwarten normalerweise nicht, dass Untersammlungen null sind.

+0

Gibt es einen Grund, warum Sie die Sammlung nicht im Feld für private Elemente initialisieren? Ich kann sehen, dass Sie, wenn Sie nicht auf den Getter der Items-Eigenschaft zugegriffen haben, nicht an einer leeren Auflistungsreferenz hängen, sondern dass Sie jedes Mal den Preis eines Null-Checks bezahlen. Ist es nur situationsbedingt? – Shaun