Come usare la lista / array di alcune eredità oggetto con Protobuf / Protobuf-net?
-
20-09-2019 - |
Domanda
Utilizzando Protobuf / Protobuf-net e due classi, una classe di base e l'altro derivato dalla base.
Come si serializzare / deserializzare una lista?
Per esempio:
public class SomeBase
{
...
}
public class SomeDerived : SomeBase
{
...
}
E il seguente campo da serializzare:
public List<SomeBase> SomeList;
Tieni presente che l'elenco contiene SomeBase e SomeDerived oggetti.
Soluzione
Per ottenere questo lavoro, è sufficiente assegnare un tag (numero) che utilizzerà per identificare il sottotipo. Fondamentalmente, il core "protocollo buffer" wire spec non gestisce l'ereditarietà, così protobuf-net lo realizza modellando eredità come incapsulamento. È possibile assegnare tag sulle proprietà / campi con [ProtoMember]
e sottotipi via [ProtoInclude]
(confronta con [XmlInclude]
).
Si noti che i tag devono essere univoci all'interno di qualsiasi solo tipo, ma che possono essere riutilizzate in sotto-tipi -. Come mostrato nell'esempio da entrambi i livelli utilizzando tag 1
In questo modo:
using System.Collections.Generic;
using ProtoBuf;
[ProtoContract]
[ProtoInclude(20, typeof(SomeDerived))]
public class SomeBase
{
[ProtoMember(1)]
public string BaseProp { get; set; }
}
[ProtoContract]
public class SomeDerived : SomeBase
{
[ProtoMember(1)]
public int DerivedProp { get; set; }
}
[ProtoContract]
public class SomeEntity
{
[ProtoMember(1)]
public List<SomeBase> SomeList;
}
class Program
{
static void Main()
{
SomeEntity orig = new SomeEntity
{
SomeList = new List<SomeBase> {
new SomeBase { BaseProp = "abc"},
new SomeDerived { BaseProp = "def", DerivedProp = 123}
}
};
var clone = Serializer.DeepClone(orig);
// clone now has a list with 2 items, one each SomeBase and SomeDerived
}
}