C# protobuf网中的对象继承

C# protobuf网中的对象继承,c#,protobuf-net,C#,Protobuf Net,考虑到这些类别定义: [ProtoContract, ProtoInclude(2, typeof(Class2))] class Class1 { [ProtoMember(1)] public string Field1 { get; set; } } [ProtoContract] class Class2 : Class1 { [ProtoMember(1)] public string Field2 { get; set; } } 我正在努力实现以下

考虑到这些类别定义:

[ProtoContract, ProtoInclude(2, typeof(Class2))]
class Class1
{
    [ProtoMember(1)]
    public string Field1 { get; set; }
}

[ProtoContract]
class Class2 : Class1
{
    [ProtoMember(1)]
    public string Field2 { get; set; }
}
我正在努力实现以下目标:

using (var ms = new MemoryStream())
{
    var c1 = new Class1 { Field1 = "hello" };
    Serializer.Serialize<Class1>(ms, c1);

    ms.Position = 0;

    var c2 = Serializer.Deserialize<Class2>(ms);
}
使用(var ms=new MemoryStream())
{
var c1=new Class1{Field1=“hello”};
序列化器。序列化(ms,c1);
ms.Position=0;
var c2=序列化程序。反序列化(ms);
}
但我得到了以下异常:
无法将类型为“ProtoBufTest.Class1”的对象强制转换为类型为“ProtoBufTest.Class2”


我真的不理解这个问题;我的理解是,当反序列化时,OrthBuf应该只考虑传入的流作为字节集合,那么为什么它显然先反序列化为<代码> Cult1对象,然后尝试将它放入<代码>类2>代码>?/P> < P>,因为您正在发送Case1,而不是Cyr2的实例。 若使用Class1实例调用方法,则无法将其magicaly转换为Class2

您可以创建Class2的新实例,并由Class1实例中的成员填充。
但它看起来像是糟糕的设计。

通过添加
[ProtoInclude(…)]
,您告诉protobuf net以允许继承工作的方式处理
Class1
Class2
。无论您是指定
还是
,protobuf net都将从基本类型开始,并向上构建;从本质上讲,您的模型已成为(用protobuf术语):

如果存在
.Class2
实例,它将反序列化为
Class2
;否则它将反序列化为
Class1
。这是有意的,这样如果你序列化一个
Class1
你会得到一个
Class1
,如果你序列化一个
Class2
你会得到一个
Class2

如果您想分别考虑这两种类型,<强>不要添加代码> [OPTICAN] 。事实上,在这种情况下,您甚至可以使用

Serializer.ChangeType
执行序列化/反序列化的往返:

var c1 = new Class1 { Field1 = "hello" };
var c2 = Serializer.ChangeType<Class1, Class2>(c1);

(虽然我不知道为什么)

在调用Serializer.Deserialize(ms)时,序列化程序接收到的唯一内容是一个不引用Class1的流(类型名不会被序列化),那么为什么会在这里弹出“Class1”?根据你使用ProtoInclude属性时包含类型的元信息。我从这个链接了解到ProtoInclude为子类的内容插入了一个“占位符”,但实际的类型信息没有嵌入。因此,当从Class1反序列化流时,Protobuf发现这个占位符为空,所以它猜测应该将其反序列化为Class1,而不是Class2。我希望Class2的特定字段保留为空/默认值…感谢您的详细解释。实际上,我并不真正需要Class2中的任何ProtoMember,因为我的用例是反序列化Class1,并在将其发送到客户机之前使用其他字段对其进行扩充(使用JSON序列化对象中的“flat”字段)。我尝试了Serializer.ChangeType,但结果中Field1和Field2都为空。@ThomasWeiss在这里工作正常。。。需要看到一个它不工作的例子,通过使用我文章中没有ProtoInclude的类定义,调用c2=Serializer.ChangeType(c1),我得到c2.Field1=null和c2.Field2=“hello”。
var c1 = new Class1 { Field1 = "hello" };
var c2 = Serializer.ChangeType<Class1, Class2>(c1);
[ProtoContract]
class Class1
{
    [ProtoMember(1)]
    public string Field1 { get; set; }
}

[ProtoContract]
class Class2
{
    [ProtoMember(1)]
    public string Field2 { get; set; }
}