ProtoInclude属性意味着什么(在protobuf-net中)

Mik*_*scu 18 .net c# protocol-buffers protobuf-net

ProtoBuf-Net实现中,ProtoInclude属性意味着什么,它有什么作用?

一个例子将不胜感激.

在这篇文章中看到了它,我不确定它是做什么的.这个例子是:

[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; }
    }
}
Run Code Online (Sandbox Code Playgroud)

另外,有没有办法使用protogen工具生成这种继承?

Mar*_*ell 23

对不起,我不是故意错过这个 - 唉,我什么都看不到.

鉴于问题的具体细节,我将假设你至少熟悉.proto; 如果我错了,请纠正我.

[ProtoInclude]就像很多[XmlInclude]XmlSerializer-或[KnownType]DataContractSerializer-它允许它在(反)序列识别类的子类.唯一的补充是它需要一个标记(数字)来标识每个子类型(必须是唯一的,而不是与父类型的任何字段冲突).

重新原型:不; 基础规范(由谷歌)未作任何规定继承可言,所以硫辛酸(通过.proto)没有这样的机制来表达这一点.protobuf-net提供继承支持作为扩展,但它仍然以一种方式使消息与其他实现保持线路兼容.在一推,也许我可以通过在谷歌规范新扩展属性添加硫辛酸的支持,但我没有这样做呢.

所以; 看一下这个例子; 表达BaseMessage和之间的继承关系BeginRequest; 不管你是否这样做:

Serialize<BaseMessage>(...)
Serialize<BeginRequest>(...)
Run Code Online (Sandbox Code Playgroud)
  • 无论哪种方式,它将从base(BaseMessage)开始并向上工作; 这不完全正确 - 它以数据开头写入BeginRequest(因此它知道我们BeginRequest在反序列化期间尽可能早地获得).重要的是包含任何父契约类型的字段,并且序列化程序查看传入的实际对象 - 而不仅仅是您的类型.

同样,在deserilaization期间,无论您是否使用:

Deserialize<BaseMessage>(...)
Deserialize<BeginRequest>(...)
Run Code Online (Sandbox Code Playgroud)

你会得到你实际序列化的类型(大概是a BeginRequest).

在引擎盖下,出于兼容性目的(使用宽协议缓冲区规范),这类似于编写类似的东西(原谅任何错误,我的.proto生锈):

message BaseMessage {
    optional BeginRequest beginRequest = 50;
    optional uint32 messageType = 1;   
}
message BeginRequest {        
}
Run Code Online (Sandbox Code Playgroud)

(重写可能不应该指定[ProtoMember],顺便说一句.

通常情况下,它会写在上升标记顺序领域,而是要进行有效的反序列化引擎厚脸皮选择写子类数据第一(这是明确的规范允许的) -即它写像(你必须想象二进制...):

[tag 50, string][length of sub-message][body of sub-message][tag 1, int][value]
Run Code Online (Sandbox Code Playgroud)

(在这种情况下,子消息的主体是空的)

这涵盖了吗?