Как распределяется / размещается int ProtoMember/ProtoInclude в ProtoBuf?
У меня есть несколько вопросов о том, как / где идентификатор [ProtoContract]
должен быть объявлен.
Представьте себе следующий код:
[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 здесь?
- Должен ли я объявить это здесь или непосредственно в RootClass?
- Могу ли я использовать идентификатор 100 здесь?
- Могу ли я использовать идентификатор 1 здесь? или участник + включить поделиться идентификатором?
- Могу ли я использовать 1 здесь? Поскольку родитель уже использует его, но это другой класс
- Могу ли я использовать 2 здесь? Так как SomeClassC уже использует это и является родным братом?
Дело в том, что у нас есть огромная модель с множеством классов, которые все наследуются от одного и того же объекта, поэтому я пытаюсь выяснить, к какому идентификатору следует позаботиться.
1 ответ
Укороченная версия:
- набор номеров полей для типа представляет собой объединение чисел, определенных для элементов (полей и свойств), и чисел, определенных для непосредственных подтипов (включает в себя)
- набор номеров полей должен быть уникальным в этом единственном типе - не требуется учитывать базовые типы или производные типы
Более длинная версия:
Причина этого заключается в том, что подтипы по существу отображаются как необязательные поля:
[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
смысл.
Чтобы ответить на конкретные вопросы, тогда:
- нет, потому что это будет противоречить
NodeId
- это должно быть объявлено
SomeClassA
; Protobuf-net ожидает только непосредственных потомков, и он сохраняет нумерацию согласованной и удобной для чтения, поскольку номер поля требуется только для того, чтобы не конфликтовать с членамиSomeClassA
- Да, ты можешь; нет конфликта
- нет, потому что это будет противоречить
Name
- Да, ты можешь; нет конфликта
Да, ты можешь; конфликта нет - хотя на самом деле protobuf-net даже не подумает
SomeClassD
в любом случае как родного брата (он нигде не рекламируется как включаемый), но если[ProtoInclude(201, typeof(SomeClassD))]
наSomeClassA
тогда было бы хорошо. Это изменит наш.proto
добавить:optional SomeClassD _alsoNotNamed = 201;
в
message SomeClassA
, и добавить:message SomeClassD { optional int32 Count = 2; }
Обратите внимание, что protobuf-net на самом деле не генерирует .proto
синтаксис, если вы явно не попросите его (через GetSchema<T>
и т. д.) Я включил его исключительно в иллюстративных целях с точки зрения основополагающих концепций protobuf.