2013-05-05 13 views
9

È venuto attraverso protobuf-net, fantastico! Ho una domanda riguardante la serializzazione delle liste vuote.Protobuf-Net Lista vuota

comincio dichiarando l'oggetto che voglio serializzare:

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

    public TestClass() { } 

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

Se _listOfInts è vuoto (ma non nullo) quando ho deserialse questo oggetto è sarà sempre nullo. Questo ha senso guardare alla convention protobuf e attualmente aggirare questo aggiungendo il seguente metodo:

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

La mia domanda è se posso realizzare questa stessa funzionalità in modo più conciso, possibilmente con un attirbute addizionale che sarà inizializzare oggetti null/vuoti come vuoti anziché null?

risposta

5

Se si sta tentando di proteggere da un elenco null, è possibile provare il caricamento lazy nel getter della proprietà.

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

In questo modo è possibile consentire al serializzatore di restituire null.

+0

Questa è una possibilità che non avevo considerato, avrei votato se potessi. Sono ancora interessato principalmente a sapere se c'è un attributo che farebbe questo per me però. – CanCan

+0

Hai provato l'attributo [DefaultValue]? Non sono sicuro di poter inizializzare gli elenchi, ma vale la pena provare. – Jras

+0

@Jras Ho pensato di aggiungere tale, ma ogni volta che l'ho guardato, si scopre che in realtà peggiorano il codice delle persone, non meglio –

6

C'è un problema fondamentale qui in termini di come protobuf codifica i dati: l'elenco stesso non appare nei dati - solo gli elementi. Per questo motivo, non è semplicemente ovvio dove archiviare informazioni sulla lista. Può essere falsificato inviando un booleano usando la serializzazione condizionale, ma francamente è un po 'hacky e brutto - e aggiunge complessità. Personalmente, raccomando vivamente di astrarre dalle liste che potrebbero mai essere nulle. Per esempio:

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

O

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

E si noti che questo consiglio non si tratta solo di serializzazione: si tratta di evitare arbitrarie nulli-reference-eccezioni. Le persone solitamente non si aspettano che le sotto-raccolte siano nulle.

+0

C'è qualche ragione per cui non inizializzi la raccolta sul campo degli articoli privati? Posso vedere che se non si è entrati nel getter della proprietà Items non si è aggrappati a un riferimento di raccolta vuoto, ma si paga il prezzo di un controllo Null ogni volta. È solo situazionale? – Shaun