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

时间:2017-07-18 08:51:00

标签: protocol-buffers protobuf-net

关于如何宣布[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吗?由于父母已经使用它,但它是一个不同的类
  6. 我可以在这里使用2吗?既然SomeClassC已经使用它并且是兄弟姐妹?
  7. 问题是我们有一个包含很多类的庞大模型,所有类都来自同一个对象,因此我想知道应该注意哪个ID。

1 个答案:

答案 0 :(得分:4)

简短版本:

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

更长的版本:

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

[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不存在冲突,并且它们不需要是唯一的。 message意义上的每.proto个数字只需要是唯一的。

采取具体问题,然后:

  1. 不,因为这会与NodeId
  2. 发生冲突
  3. 应在SomeClassA上宣布; protobuf-net只期待直接后代,并且它使编号保持一致且方便可读,因为字段编号只需要与SomeClassA的成员不冲突
  4. 是的,你可以;没有冲突
  5. 不,因为这会与Name
  6. 发生冲突
  7. 是的,你可以;没有冲突
  8. 是的,你可以;没有冲突 - 虽然实际上protobuf-net甚至不会将SomeClassD视为兄弟 (它不会作为包含在任何地方做广告) - 但是如果有{在[ProtoInclude(201, typeof(SomeClassD))]上{1}},那就没关系了。这会将我们的SomeClassA更改为添加:

    .proto

    optional SomeClassD _alsoNotNamed = 201; ,然后添加:

    message SomeClassA
  9. 请注意,protobuf-net不会实际生成message SomeClassD { optional int32 Count = 2; } 语法,除非您明确要求(通过.proto等) - 我将其纯粹包括在内在潜在的protobuf概念方面的说明性目的。