问题描述
关于如何/在何处声明 [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 个吗?
- 我应该在此处声明还是直接在 RootClass 上声明?
- 我可以在这里使用 ID 100 吗?
- 我可以在这里使用 id 1 吗?或成员 + 包括共享 ID?
- 我可以在这里使用 1 吗?由于父母已经使用它但它是一个不同的类
- 我可以在这里使用 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:
- 否,因为这会与
NodeId
冲突 - 应该在
SomeClassA
上声明;protobuf-net 只期待直接后代,它保持编号一致且便于阅读,因为字段编号只需要与SomeClassA
的成员不冲突 - 是的,你可以;没有冲突
- 不,因为这会与
Name
冲突 - 是的,你可以;没有冲突
是的,你可以;没有冲突 - 尽管实际上 protobuf-net 甚至不会将
SomeClassD
视为兄弟反正(它没有在任何地方作为包含进行宣传) - 但如果有是[ProtoInclude(201, typeof(SomeClassD))]
在SomeClassA
上,然后就可以了.这将更改我们的.proto
以添加:
- no, because that would conflict with
NodeId
- 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 ofSomeClassA
- yes you can; there is no conflict
- no, because that would conflict with
Name
- yes you can; there is no conflict
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))]
onSomeClassA
, 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?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!