本文介绍了如何在 ProtoBuf 中共享/放置 ProtoMember/ProtoInclude 的 int?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于如何/在何处声明 [ProtoContract] 的 ID,我有几个问题.

I've several questions on how/where the ID of a [ProtoContract] should be declared.

想象一下下面的代码:

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

我已经提出了几个问题:

I've put several number with questions:

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

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

The thing is that we have a huge model with a lot of classes, which all herits from the same object, so I'm trying to figure out to which ID I should take care.

推荐答案

简短版本:

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

这篇关于如何在 ProtoBuf 中共享/放置 ProtoMember/ProtoInclude 的 int?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 11:10