【问题标题】:What does the ProtoInclude attribute mean (in protobuf-net)ProtoInclude 属性是什么意思(在 protobuf-net 中)
【发布时间】:2010-10-31 03:58:24
【问题描述】:

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 工具生成这样的继承?

【问题讨论】:

标签: c# .net protocol-buffers protobuf-net


【解决方案1】:

抱歉,我不是故意错过这个 - 唉,我没有看到所有内容。

鉴于问题中的细节,我假设您至少对 .proto 非常熟悉;如果我错了,请纠正我。

[ProtoInclude] 的工作方式很像 [XmlInclude]XmlSerializer - 或 [KnownType]DataContractSerializer - 它允许它在(反)序列化期间识别类型的子类。唯一额外的一点是它需要一个标签(数字)来标识每个子类型(必须是唯一的,并且不与父类型中的任何字段冲突)。

重新原生质:不;底层规范(由 google 提供)根本没有规定继承,因此 protogen(通过 .proto)没有表达这一点的机制。 protobuf-net 作为 extension 提供继承支持,但这样做的方式仍然使消息与其他实现兼容。在推动下,也许我可以通过 google 规范中的新扩展属性添加 protogen 支持,但我还没有这样做。

所以;看例子;表示BaseMessageBeginRequest之间的继承关系;不管你是否这样做:

Serialize<BaseMessage>(...)
Serialize<BeginRequest>(...)
  • 无论哪种方式,它都会从底部(BaseMessage)开始向上工作;这不是 exactly true - 它以 BeginRequest 开头写入 data (以便在反序列化期间尽早知道我们有 BeginRequest)。重要的是包含来自任何父合约类型的字段,并且序列化程序会查看传入的 actual 对象 - 而不仅仅是您它的类型。

同样,在反序列化过程中,无论您是否使用:

Deserialize<BaseMessage>(...)
Deserialize<BeginRequest>(...)

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

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

message BaseMessage {
    optional BeginRequest beginRequest = 50;
    optional uint32 messageType = 1;   
}
message BeginRequest {        
}

(覆盖可能不应该指定[ProtoMember],顺便说一句。

通常,它会按标签升序写入字段,但为了高效反序列化,引擎厚颜无耻地选择写入子类数据first(规范明确允许) - 即它写入类似的东西(你必须想象二进制......):

[tag 50, string][length of sub-message][body of sub-message][tag 1, int][value]

(在这种情况下,子消息的正文为空)

这包括它吗?

【讨论】:

  • 是的,我认为它几乎涵盖了它。感谢您的澄清。所以从我收集到的信息来看,如果一个人想提供一个“BaseMessage”,几乎必须提前知道所有继承消息(或至少是它们的标签),对吗?......我对此很感兴趣,因为我'正在编写一个基于 ProtocolBuffers 的 RPC 引擎,我正在寻找一种方法,允许 RPC 引擎的用户在我正在使用的基本 RPC 消息之上提供他们自己的协议缓冲区消息..
  • 目前,是的;但我正在开发一个允许运行时规范的版本,并且我有一个提供未知对象支持的想法 - 但它不会在平台之间移植。 Re RPC - 我已经在 RPC 方向上完成了很多工作 - 它还没有完成,但如果你想帮忙? ;-p 为了避免创建代码生成和运行时类型,我使用了接口和表达式 - marcgravell.blogspot.com/2009/03/explaining-expression.html(尽管代码生成或运行时类型创建方法也是有效的)。例如,有一个工作的 http RPC 客户端/服务器。
  • 听起来很酷。我很想能够提供帮助,也许我们可以从我所拥有的东西中使用一些概念。我一定要看看你的工作,如果你有兴趣,我可以分享我的想法/实施..
  • 我很擅长反射/表达式/等方面的东西,但是从头开始编写 RPC 堆栈对我来说是新的,所以如果你有这方面的经验?特别是,由于确保发布所有内容等固有的复杂性,我已经避开了原始 TCP 方面。
  • 显然我完全错过了你最后的评论,并认为你失去了兴趣。我道歉!我给你发了一封电子邮件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-13
  • 1970-01-01
  • 2016-04-06
  • 2016-06-07
  • 1970-01-01
  • 2019-06-12
相关资源
最近更新 更多