对不起,我不是故意错过这个 - 唉,我没有看到一切。
鉴于问题中的细节,我将假设您至少对 .proto 非常熟悉;如果我错了,请纠正我。
[ProtoInclude]
工作原理很像[XmlInclude]
for XmlSerializer
- 或[KnownType]
for DataContractSerializer
- 它允许它在(反)序列化期间识别类型的子类。唯一额外的事情是它需要一个标签(数字)来标识每个子类型(必须是唯一的,并且不与父类型中的任何字段冲突)。
再原生质:不;底层规范(由 google 提供)根本没有提供继承,因此 protogen(通过 .proto)没有表达这一点的机制。protobuf-net 作为扩展提供继承支持,但这样做的方式仍然使消息与其他实现保持兼容。在推动下,也许我可以通过谷歌规范中的新扩展属性添加 protogen 支持,但我还没有这样做。
所以; 看例子;表示BaseMessage
和之间的继承关系BeginRequest
;无论您是否这样做:
Serialize<BaseMessage>(...)
Serialize<BeginRequest>(...)
- 无论哪种方式,它将从底部 (
BaseMessage
) 开始并向上工作;这并不完全正确 - 它以开头写入数据BeginRequest
(以便它知道我们BeginRequest
在反序列化期间尽早拥有 a )。重要的是包含来自任何父合约类型的字段,并且序列化程序会查看传入的实际对象 - 而不仅仅是您所说的类型。
同样,在反序列化期间,无论您是否使用:
Deserialize<BaseMessage>(...)
Deserialize<BeginRequest>(...)
你会得到你实际序列化的类型(大概是 a BeginRequest
)。
在引擎盖下,出于兼容性目的(使用宽协议缓冲区规范),这类似于编写类似的内容(请原谅任何错误,我的 .proto 是生锈的):
message BaseMessage {
optional BeginRequest beginRequest = 50;
optional uint32 messageType = 1;
}
message BeginRequest {
}
(覆盖可能不应该指定[ProtoMember]
,顺便说一句。
通常,它会按标签升序写入字段,但为了进行有效的反序列化,引擎厚颜无耻地选择首先写入子类数据(规范明确允许) - 即它写入类似(你必须想象二进制...):
[tag 50, string][length of sub-message][body of sub-message][tag 1, int][value]
(在这种情况下,子消息的正文为空)
这覆盖它吗?