Вам не нужно ничего особенного здесь ... поскольку protobuf-net уважает наследование. Если у вас есть:
[ProtoInclude(typeof(Foo), 20)]
[ProtoInclude(typeof(Bar), 21)]
public abstract class MyBase {
/* other members */
public byte[] GetBytes()
{
using(MemoryStream ms = new MemoryStream())
{
Serializer.Serialize<MyBase>(ms, this); // MyBase can be implicit
return ms.ToArray();
}
}
}
[ProtoContract]
class Foo : MyBase { /* snip */ }
[ProtoContract]
class Bar : MyBase { /* snip */ }
тогда это сработает. Для сериализации данных он всегда начинается с основания (контракта) типа; так что даже если вы сделали Serializer.Serialize<Foo>(stream, obj)
, первое, что он сделает, это обнаружить, что у него есть базовый класс, который является контрактом, и переключиться на MyBase
. Во время десериализации он идентифицирует правильный производный (конкретный) тип и использует его, поэтому вы можете использовать Deserialize
с MyBase
, и он будет строить Foo
или Bar
в зависимости от исходных данных.
Таким образом, следующие в основном идентичны:
Serializer.Serialize<BaseType>(dest, obj);
...
BaseType obj = Serializer.Deserialize<BaseType>(source);
и
Serializer.Serialize<DerivedType>(dest, obj);
...
DerivedType obj = Serializer.Deserialize<DerivedType>(source);
Основное различие в том, как переменные набираются.
Ну, это было неловко просто;) – Martin
Это даст вам базовый класс для всех экземпляров, если вы не измените каждый производный класс индивидуально (не уверен, что это то, что вы хотите, или нет). Есть причина, по которой protobuf.net добавил не общую версию, используя отражение ... –
Там, сделал это. Напротив автора C# в двух словах не меньше. : P –