Сделайте универсальный десериализатор с буфером протокола - PullRequest
0 голосов
/ 13 июня 2018

Я работаю с RabbitMQ и буфером протокола на C # и C ++.У меня есть 5 разных классов, каждый класс будет содержать поле «ActionType».В зависимости от номера типа действия я хочу вызвать нужную функцию, но когда я получаю сообщение от RabbitMQ, я не знаю, какому классу принадлежит сообщение, когда я хочу десериализовать сообщение.Есть ли способ десериализации / преобразования сообщения в общий объект, или, может быть, я могу получить только значение из типа действия и затем десериализовать сообщение?

1 Ответ

0 голосов
/ 13 июня 2018

В терминах protobuf это звучит как сценарий oneof с 5 суб-сообщениями.oneof даст вам перечисление дискриминатора и 5 сообщений.Значение:

message OuterMesage {
    oneof actionType {
        Foo foo = 1;
        Bar bar = 2;
        ...
    }
}
message Foo {...}
message Bar {...}
...

Вы десериализуете данные как OuterMesage и проверяете через .actionTypeCase (обычно в switch), какой из .foo / .bar и т. Д. Смотреть.


Обратите внимание, что если вы используете protobuf-net, этот точно такой же сценарий также может быть смоделирован в наследование, что позволяет использовать полиморфизм;то есть

[ProtoContract]
[ProtoInclude(1, typeof(Foo)]
[ProtoInclude(2, typeof(Bar)]
public class OuterMessage { ... }

[ProtoContract]
public class Foo : OuterMessage {}

[ProtoContract]
public class Bar : OuterMessage {}

Это на самом деле точно такой же макет данных , за исключением того, что теперь сообщение, возвращаемое вами после десериализации OuterMessage, будет Foo, Bar и т. д.- по мере необходимости.Поэтому, если у вас есть virtual (или abstract) метод для OuterMessage, вы можете использовать полиморфизм для вызова соответствующего:

var obj = Serializer.Deserialize<OuterMessage>(data); // obj could be Foo/Bar/etc
obj.DoTheThing(); // your virtual method
...