ProtoBuf 中的 shared/placed 是 ProtoMember/ProtoInclude 的整数吗?

How are shared/placed the int of the ProtoMember/ProtoInclude in ProtoBuf?

我有几个关于 how/where 应该声明 [ProtoContract] 的 ID 的问题。

想象一下下面的代码:

[ProtoContract]
[ProtoInclude(100, typeof(SomeClassA))]//1) CAN I USE 1 here?
public abstract class RootClass{
    [ProtoMember(1)]
    public int NodeId {get;set;}
}

[ProtoContract]
[ProtoInclude(200, typeof(SomeClassC)]//2) Should I declare this here or directly on the RootClass?
//3) Can I use the id 100 here?
//4) Can I use the id 1 here? or member + include share the id?
public class SomeClassA : RootClass{

    [ProtoMember(1)]//5) CAN I USE 1 here? Since the parent already use it but it's a different class
    public String Name{get;set;}
}

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

[ProtoContract]
public class SomeClassD : SomeClassA {
    [ProtoMember(2)] //6) Can I use 2 here? Since SomeClassC already use it and is a sibling?
    public int Count{get;set;}
}

我已经放了几个有问题的号码:

  1. 我可以在这里使用 1 吗?
  2. 我应该在这里声明还是直接在 RootClass 上声明?
  3. 我可以在这里使用 id 100 吗?
  4. 我可以在这里使用id 1吗?或会员+包括分享ID?
  5. 我可以在这里使用 1 吗?由于 parent 已经在使用它,但它是一个不同的 class
  6. 这里可以用2吗?既然 SomeClassC 已经使用它并且是兄弟?

问题是我们有一个包含很多 classes 的巨大模型,所有这些都来自同一个 object,所以我想弄清楚我应该使用哪个 ID保重。

简短版本:

  • 类型的字段编号集是针对 members(字段和属性)定义的编号的 union,以及为 直接子类型定义的数字 (包括)
  • 字段编号集在单一类型中必须是唯一的 - 不需要考虑基本类型或派生类型

更长的版本:

原因是子类型本质上映射为可选字段:

[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 个子类型字段,因此出于 .proto 的目的,可以将其视为 oneof。与子类型相关的任何字段都将包含在 message SomeClassA 中,因此与 RootClass 没有冲突,并且它们不需要是唯一的。在 .proto 意义上,每个 message 的数字只需要是唯一的。


做具体问题,则:

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

    optional SomeClassD _alsoNotNamed = 201;
    

    message SomeClassA,并添加:

    message SomeClassD {
        optional int32 Count = 2;
    }
    

请注意,protobuf-net 实际上 生成 .proto 语法,除非您明确要求(通过 GetSchema<T> 等)- 我' m 包含它纯粹是为了说明底层 protobuf 概念。