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

J4N*_*J4N 4 protocol-buffers protobuf-net

我有几个关于如何/在哪里[ProtoContract]声明a 的 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;}
}
Run Code Online (Sandbox Code Playgroud)

我已经提出了几个问题:

  1. 我可以在这里使用 1 吗?
  2. 我应该在这里声明还是直接在 RootClass 上声明?
  3. 我可以在这里使用 id 100 吗?
  4. 我可以在这里使用 id 1 吗?或成员 + 包括共享 ID?
  5. 我可以在这里使用 1 吗?由于父母已经使用它但它是一个不同的类
  6. 我可以在这里使用 2 吗?由于 SomeClassC 已经使用它并且是兄弟姐妹?

问题是我们有一个包含很多类的巨大模型,它们都继承自同一个对象,所以我试图弄清楚我应该注意哪个 ID。

Mar*_*ell 5

精简版:

  • 一类型的组场数是联合针对所定义的数字成员(字段和属性),以及用于定义这些数字直接亚型(包括)
  • 字段编号集在该单一类型中必须是唯一的- 不需要考虑基类型或派生类型

更长的版本:

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

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

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

请注意,最多将使用 1 个子类型字段,因此可以考虑oneof用于.proto. 与子类型相关的任何字段都将包含在 中message SomeClassA,因此与 没有冲突RootClass并且它们不需要是唯一的。这些数字只需要message在.proto某种意义上是唯一的。


要回答具体问题,然后:

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

    optional SomeClassD _alsoNotNamed = 201;
    
    Run Code Online (Sandbox Code Playgroud)

    到message SomeClassA,并添加:

    message SomeClassD {
        optional int32 Count = 2;
    }
    
    Run Code Online (Sandbox Code Playgroud)

需要注意的是protobuf网并不实际产生的.proto语法,除非您明确要求它(通过GetSchema<T>等) -我纯粹是为了说明的目的,包括它的基本概念protobuf的术语。