2009-09-01 1 views
2

Использование Protobuf/Protobuf-net и двух классов, одного базового класса и другого, полученного из базы.
Как бы вы сериализовали/десериализовали список?Как использовать список/массив некоторого наследования объектов с Protobuf/Protobuf-net?

Например:

public class SomeBase 
{ 
    ... 
} 

public class SomeDerived : SomeBase 
{ 
    ... 
} 

И следующее поле для сериализации:

public List<SomeBase> SomeList; 

Имейте в виду, что список содержит SomeBase и SomeDerived объектов.

ответ

3

Чтобы заставить это работать, вам просто нужно назначить тег (номер), который он будет использовать для идентификации подтипа. В принципе, спецификация проводника «протокольные буферы» не обрабатывает наследование, поэтому protobuf-net достигает этого путем моделирования наследования как инкапсуляции. Вы присваиваете метки свойствам/полям [ProtoMember], а подтипы - через [ProtoInclude] (сравните с [XmlInclude]).

Обратите внимание, что метки должны быть уникальными в пределах любого одного типа, но они могут быть повторно использованы в подтипов - как показано в примере с помощью обоих уровней с помощью тега 1.

Как так:

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 
    } 
} 
+0

Отличный ответ, как всегда! –

+0

2 вопроса: сможет ли кто-нибудь на другом конце провода справиться с этим в Java/C++? и второй вопрос: возможно ли это с .proto? (если оба да, вы можете дать .proto sample? ty –

+0

@David protobuf-net реализует наследование через инкапсуляцию, поэтому SomeBase будет иметь необязательное поле типа SomeDerived, с полем № 20 GetProto/GetSchema проиллюстрирует это. Однако protobuf-net не * генерирует * наследование на уровне codegen (если он начинается с .proto), потому что у .proto нет метафоры для описания такого. –