且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在 ProtoBuf ***享/放置 ProtoMember/ProtoInclude 的 int?

更新时间:2023-02-17 15:22:55

简短版本:

  • 类型的字段编号集是针对成员(字段和属性)定义的编号以及为直接子类型定义的编号的联合(包括)
  • 字段编号集在单一类型中必须是唯一的 - 不需要考虑基本类型或派生类型
  • the set of field numbers for a type is the union of the numbers defined against members (fields and properties), and the numbers defined for immediate subtypes (includes)
  • the set of field numbers must be unique within that single type - it is not required to consider base types or derived types

更长的版本:

这样做的原因是子类型本质上被映射为可选字段:

The reason for this is that subtypes are essentially mapped as optional fields:

[ProtoContract]
[ProtoInclude(100, typeof(SomeClassA))]
public abstract class RootClass{
    [ProtoMember(1)]
    public int NodeId {get;set;}
}

[ProtoContract]
[ProtoInclude(200, typeof(SomeClassC)]
public class SomeClassA : RootClass{

    [ProtoMember(1)]
    public String Name{get;set;}
}

[ProtoContract]
public class SomeClassC : SomeClassA {
    [ProtoMember(2)]
    public int Count{get;set;}
}

是,就 proto2 语法而言:

message RootClass {
    optional int32 NodeId = 1;
    optional SomeClassA _notNamed = 100;
}
message SomeClassA {
    optional string Name = 1;
    optional SomeClassC _notNamed = 200;
}
message SomeClassC {
    optional int32 Count = 2;
}

请注意,最多会使用 1 个子类型字段,因此可以将其视为 oneof 用于 .proto 的目的.message SomeClassA 中会包含与子类型相关的任何字段,因此与 RootClass 没有冲突,它们不需要唯一.在 .proto 意义上,每个 message 的数字只需要是唯一的.

Note that at most 1 sub-type field will be used, so it can be considered oneof for the purposes of .proto. Any fields relating to the sub-type will be included in message SomeClassA, so there is no conflict with RootClass and they do not need to be unique. The numbers only need to be unique per message in the .proto sense.

要回答具体问题,然后:

To take the specific questions, then:

  1. 否,因为这会与 NodeId
  2. 冲突
  3. 应该在SomeClassA上声明;protobuf-net 只期待直接后代,它保持编号一致且便于阅读,因为字段编号只需要与 SomeClassA
  4. 的成员不冲突
  5. 是的,你可以;没有冲突
  6. 不,因为这会与 Name
  7. 冲突
  8. 是的,你可以;没有冲突
  9. 是的,你可以;没有冲突 - 尽管实际上 protobuf-net 甚至不会将 SomeClassD 视为兄弟反正(它没有在任何地方作为包含进行宣传) - 但如果有是 [ProtoInclude(201, typeof(SomeClassD))]SomeClassA 上,然后就可以了.这将更改我们的 .proto 以添加:

  1. no, because that would conflict with NodeId
  2. it should be declared on SomeClassA; protobuf-net is only expecting immediate descendants, and it keeps the numbering consistent and conveniently readable, since the field number is only required to not conflict with the members of SomeClassA
  3. yes you can; there is no conflict
  4. no, because that would conflict with Name
  5. yes you can; there is no conflict
  6. yes you can; there is no conflict - although actually protobuf-net won't even think of SomeClassD as a sibling anyway (it isn't advertised anywhere as an include) - but if there was a [ProtoInclude(201, typeof(SomeClassD))] on SomeClassA, then it would be fine. This would change our .proto to add:

optional SomeClassD _alsoNotNamed = 201;

消息SomeClassA,并添加:

message SomeClassD {
    optional int32 Count = 2;
}

请注意,protobuf-net 不会实际上生成 .proto 语法,除非您明确要求(通过 GetSchema等) - 我将它包含在内纯粹是为了说明底层 protobuf 概念.


Note that protobuf-net doesn't actually generate the .proto syntax unless you explicitly ask for it (via GetSchema<T> etc) - I'm including it purely for illustrative purposes in terms of the underlying protobuf concepts.