Protobuf - это формат сериализации на основе контракта, разработанный для обеспечения независимости от платформы. Таким образом, метаданные типа no включены в провод, поскольку они не будут применяться между платформами. Даже наследование не является частью спецификации ядра protobuf. * 1003 *
protobuf-net как специфическая реализация вводит поддержку наследования (через дым и зеркала), но в идеале все же должно быть возможно заранее определить ожидаемые типы - точно так же, как другие сериализаторы как XmlSerializer
или DataContractSerializer
. Это можно сделать с помощью [ProtoInclude(...)]
для указания ожидаемых конкретных типов.
Если вы действительно не можете заранее определить фактические типы, существует также опция DynamicType
, которая записывает AssemblyQualifiedName в поток. Если вас интересует этот маршрут, обратите внимание, что «кроссплатформенные» возможности формата начинают выходить из строя, но он очень полезен для целей .NET-to-.NET.
В самом простом, обертка, такая как:
[ProtoContract]
public class SomeWrapper {
[ProtoMember(1, DynamicType = true)]
public object Value {get;set;}
}
Оберните ваш объект в , чтобы и он должен себя вести (по крайней мере, в v2; DynamicType не существовал в v1). Полный пример:
[TestFixture]
public class SO7218127
{
[Test]
public void Test()
{
var orig = new SomeWrapper {Value = new SubType { Foo = 123, Bar = "abc"}};
var clone = Serializer.DeepClone(orig);
Assert.AreEqual(123, orig.Value.Foo);
Assert.AreEqual("abc", ((SubType) clone.Value).Bar);
}
[ProtoContract]
public class SomeWrapper
{
[ProtoMember(1, DynamicType = true)]
public BaseType Value { get; set; }
}
[ProtoContract]
public class BaseType
{
[ProtoMember(1)]
public int Foo { get; set; }
}
[ProtoContract]
public class SubType : BaseType
{
[ProtoMember(2)]
public string Bar { get; set; }
}
}