C# ProtoInclude 属性是什么意思(在 protobuf-net 中)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/947666/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 04:00:42  来源:igfitidea点击:

What does the ProtoInclude attribute mean (in protobuf-net)

c#.netprotocol-buffersprotobuf-net

提问by Mike Dinescu

In the ProtoBuf-Netimplementation, what does the ProtoIncludeattribute mean, and what does it do?

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

An example would be appreciated.

一个例子将不胜感激。

I saw it in this postand I'm not sure what it does. The example was:

在这篇文章中看到了它,但我不确定它的作用。这个例子是:

[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; }
    }
}

Also, is there a way to generate such inheritance using the protogentool?

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

采纳答案by Marc Gravell

Sorry, I didn't mean to miss this one - alas, I don't see everything.

对不起,我不是故意错过这个 - 唉,我没有看到一切。

Given the specifics in the question, I'm going to assume that you are at least passingly familiar with .proto; correct me if I am wrong.

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

[ProtoInclude]works a lot like [XmlInclude]for XmlSerializer- or [KnownType]for DataContractSerializer- it allows it to recognise subclasses of a type during (de)serialization. The only additional thing is that it needs a tag (number) to identify each sub-type (that must be unique, and not clash with any of the fields from the parent type).

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

Re protogen: nope; the underlying spec (by google) makes no provision for inheritance at all, so protogen (via .proto) has no mechanism to express this. protobuf-net provides inheritance support as an extension, but does it in a way that still leaves the messages wire-compatible with the other implementations. At a push, maybeI could add protogen support via the new extension properties in the google spec, but I haven't done this yet.

再原:不;基础规范(由谷歌),使得继承没有规定在所有的,所以硫辛酸(通过.proto)没有这样的机制来表达这一点。protobuf-net 提供继承支持作为扩展,但它的方式仍然使消息与其他实现保持兼容。在推动下,也许我可以通过 google 规范中的新扩展属性添加对 protogen 的支持,但我还没有这样做。

So; to look at the example; that expresses an inheritance relationship between BaseMessageand BeginRequest; regardless of whether you do:

所以; 看例子;表示BaseMessage和之间的继承关系BeginRequest;不管你是否:

Serialize<BaseMessage>(...)
Serialize<BeginRequest>(...)
  • either way, it will start at the base (BaseMessage) and work upwards; which isn't exactlytrue - it writes the datastarting with BeginRequest(so that it knows we have a BeginRequestas early as possible during deserialization). The important thing is that the fields from any parent contract types is included, and the serializer looks at the actualobject passed in - not just the type you sayit is.
  • 无论哪种方式,它都会从底部 ( BaseMessage) 开始并向上工作;这并不完全正确 - 它以( 以便它知道我们在反序列化过程中尽早知道我们有一个 )开头的数据。重要的是包含来自任何父合同类型的字段,并且序列化程序查看传入的实际对象 - 而不仅仅是您所说的类型。BeginRequestBeginRequest

Likewise, during deserilaization, regardless of whether you use:

同样,在脱丝过程中,无论您是否使用:

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

you will get the type you actually serialized (presumably a BeginRequest).

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

Under the bonnet, for compatibility purposes (with the wide protocol buffers specification), this is similar to writing something like (forgive any errors, my .proto is rusty):

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

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

(the override probably shouldn't specify [ProtoMember], btw.

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

Normally, it would write fields in ascending tag order, but to make for efficient deserialization the engine cheekily chooses to write the subclass data first(which is explicitly allowed by the spec) - i.e. it writes something like (you'll have to imagine the binary...):

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

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

(in this case, the body of the sub-message is empty)

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

Does that cover it?

这涵盖了吗?