Как распределяется / размещается 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. Могу ли я использовать 1 здесь?
  2. Должен ли я объявить это здесь или непосредственно в RootClass?
  3. Могу ли я использовать идентификатор 100 здесь?
  4. Могу ли я использовать идентификатор 1 здесь? или участник + включить поделиться идентификатором?
  5. Могу ли я использовать 1 здесь? Поскольку родитель уже использует его, но это другой класс
  6. Могу ли я использовать 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 смысл.


Чтобы ответить на конкретные вопросы, тогда:

  1. нет, потому что это будет противоречить NodeId
  2. это должно быть объявлено SomeClassA; Protobuf-net ожидает только непосредственных потомков, и он сохраняет нумерацию согласованной и удобной для чтения, поскольку номер поля требуется только для того, чтобы не конфликтовать с членами SomeClassA
  3. Да, ты можешь; нет конфликта
  4. нет, потому что это будет противоречить Name
  5. Да, ты можешь; нет конфликта
  6. Да, ты можешь; конфликта нет - хотя на самом деле 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.

Другие вопросы по тегам