在ProtoBuf-Net实施中, ProtoInclude 属性是什么意思,它有什么作用?
一个例子将不胜感激。
我看到它in this post而且我不确定它是做什么的。例子是:
[Serializable,
ProtoContract,
ProtoInclude(50, typeof(BeginRequest))]
abstract internal class BaseMessage
{
[ProtoMember(1)]
abstract public UInt16 messageType { get; }
}
[Serializable,
ProtoContract]
internal class BeginRequest : BaseMessage
{
[ProtoMember(1)]
public override UInt16 messageType
{
get { return 1; }
}
}
另外,有没有办法使用 protogen 工具生成这种继承?
答案 0 :(得分:22)
对不起,我不是故意错过这个 - 唉,我什么都看不到。
鉴于问题的具体细节,我将假设你至少熟悉.proto;如果我错了,请纠正我。
[ProtoInclude]
与[XmlInclude]
的{{1}}或XmlSerializer
的{{1}}非常相似 - 它允许它在(de)期间识别某个类型的子类序列化。唯一的另一件事是它需要一个标签(数字)来标识每个子类型(必须是唯一的,而不是与父类型中的任何字段冲突)。
Re protogen:nope;基础规范(通过谷歌)没有提供继承的所有,因此protogen(通过.proto)没有机制来表达这一点。 protobuf-net提供继承支持作为扩展,但它仍然以使得消息与其他实现有线兼容的方式进行。在推动,也许我可以通过谷歌规范中的新扩展属性添加protogen支持,但我还没有这样做。
因此;看一下这个例子;表示[KnownType]
和DataContractSerializer
之间的继承关系;不管你是否这样做:
BaseMessage
BeginRequest
)开始向上工作;这不是完全为真 - 它以Serialize<BaseMessage>(...)
Serialize<BeginRequest>(...)
开头写出数据(这样它就知道我们在BaseMessage
期间尽早发现BeginRequest
反序列化)。重要的是包含任何父合同类型的字段,并且序列化程序会查看传入的实际对象 - 而不仅仅是所说的类型。< / LI>
同样,在去除分类期间,无论您是否使用:
BeginRequest
您将获得实际序列化的类型(可能是Deserialize<BaseMessage>(...)
Deserialize<BeginRequest>(...)
)。
在引擎盖下,出于兼容性目的(使用宽协议缓冲区规范),这类似于编写类似的内容(原谅任何错误,我的.proto生锈):
BeginRequest
(覆盖可能不应指定message BaseMessage {
optional BeginRequest beginRequest = 50;
optional uint32 messageType = 1;
}
message BeginRequest {
}
,顺便说一句。
通常情况下,它会按升序标记顺序写入字段,但为了实现高效的反序列化,引擎会选择先编写子类数据 (规范明确允许) - 即写入类似的东西(你必须想象二进制......):
[ProtoMember]
(在这种情况下,子消息的正文是空的)
这涵盖了吗?