Как описано в этом посте , мы можем использовать атрибут ProtoInclude для управления сериализацией иерархии классов.И если мы будем использовать только protobuf-net, он будет работать в обоих направлениях.Но проблема возникает, когда мы пытаемся десериализовать сообщения, сериализованные «внешними» реализациями унаследованных протокольных буферов, напр.Java и т. Д.
Как уже упоминалось в этом посте выше, Protobuf-net распознает иерархию классов по «обращенным» последовательностям байтов, когда дочерние поля классов сериализуются перед родительскими.Но устаревший код сериализует их в «правильном» порядке, и protobuf-net создает исключение «Невозможно привести объект типа« А »к типу B». исключение во время десериализации.В обратном направлении все работает нормально, унаследованный код может десериализовать «иерархические» сообщения, создаваемые библиотекой protobuf-net.
Я не могу повлиять на порядок сериализации байтов на противоположной стороне канала.Как я могу правильно десериализовать этот тип сообщений на стороне .NET protobuf-net?
Обновление: примеры кода
На нашем конце строки у нас есть оригинальные иерархические классы protobuf-net:
[ProtoContract, ProtoInclude(10, typeof(B))]
public class A
{
[ProtoMember(1)]
public int Age;
}
public class B : A
{
[ProtoMember(2)]
public int Balls;
}
На другом концеклассы строк генерируются с использованием файла .proto:
message B {
optional int32 balls = 2;
}
message A {
optional int32 age = 1;
optional B b = 10;
}
Пример сгенерированных классов, мы могли бы использовать генератор protobuf-net для их создания для .NET:
[ProtoContract]
public class A_generated
{
[ProtoMember(1)]
public int Age;
[ProtoMember(10)]
public B b;
}
[ProtoContract]
public class B_generated
{
[ProtoMember(2)]
public int Balls;
}
Так что теперь,давайте сериализуем и десериализуем класс B:
- Сериализуем и десериализуем обратно оригинальные классы - ОК
- Сериализуем и десериализуем обратно созданные классы - ОК
- Сериализация оригинал и десериализация как сгенерированный - ОК
- Сериализация сгенерированный и десериализация как оригинал - FAIL , "Невозможно привести объект типа 'A' к типу 'B'." исключение
Я исследовал полученные байты и обнаружилразница - порядка байтов .
Пример: пусть Age = 10 и Balls = 23.Затем:
- оригинал B, сериализованный: [82, 2, 16, 23, 8, 10], может быть десериализован с использованием обоих как оригинал как сгенерировано классов;
- сгенерировано B сериализовано: [8, 10, 82, 2, 16, 23], НЕ может быть десериализовано с использованием protobuf-net original классы выше.
Надеюсь, теперь все достаточно ясно, и я хочу получить положительный ответ: да, есть способ использовать ProtoInclude и десериализовать универсальные классы.