как использовать расширения из буферов протокола для поддержания «общего» сообщения - PullRequest
2 голосов
/ 05 июня 2011

Мое общение клиент-сервер выглядит следующим образом: существуют некоторые так называемые объявления, которые являются отдельными сообщениями, используемыми для обмена информацией. Идея заключается в том, что объявление является общей частью каждого сообщения. На самом деле я предполагаю, что это будет тип сообщения. Тип решает, что является содержанием. В диаграмме классов UML Annoucement будет классом, который наследуют все другие сообщения.

Я хочу реализовать эту идею в коммуникации между двумя приложениями, одно из которых написано на C ++, а другое на C #. Я думал, что мог бы написать сообщение, которое содержит одно поле с типом, если сообщение (поле enum). Вся дополнительная информация, относящаяся к типу, будет реализована как расширение.

Я нашел несколько примеров, как использовать расширения в C ++, однако я понятия не имею, как это сделать в C #. Я знаю, что есть интерфейсы IExtensible и IExtension (в protobuf-net), но как их использовать? Интернет-ресурсы кажутся бедными в этом вопросе.

Я предполагаю, что в прошлом сообщения в C # определяли аналогично тому, что они все еще определены в приложениях C ++ (с использованием файла proto и protoc). Могу ли я использовать тот же файл прото для определения сообщения в C #? Как? Будут ли расширения интерпретироваться или переопределяться?

Если бы я мог внедрить расширения, я бы отправил сообщение, проанализировал его, проверил тип и использовал функцию approriate для его поддержки. Это звучит для меня круто, потому что мне не нужно было заботиться о типе сообщения, которое я собирался прочитать - мне не нужно знать тип перед анализом.

1 Ответ

0 голосов
/ 05 июня 2011

Есть несколько способов сделать это. Я не на самом деле уверен, что расширения, это то, что я бы прыгнул, но:

в вашем типе сообщения вы можете иметь набор полностью определенных полей для каждого под-сообщения, т.е.

base-message
  {1-5} common fields
  {optional 20} sub-message 1
  {optional 21} sub-message 2
  {optional 22} sub-message 3
  {optional 23} sub-message 4
sub-message 1
  {1-n} specific fields

где у вас будет ровно один объект под-сообщения

альтернативно, инкапсулирует общие части внутри более конкретного сообщения:

common field type
  {1-n} fields
sub-message 1
  {1} common field type
  {2-m} specific fields

Любой подход позволит вам десериализовать; вторая сложнее, IMO, так как она требует, чтобы вы знали тип заранее. Единственный удобный способ сделать это - префикс каждого идентификатора. Лично я предпочитаю первое. Это, однако, не требует расширений - так как мы знаем все заранее. Как это происходит, во-первых, также как protobuf-net реализует наследование, так что вы можете сделать это с наследованием типов (4 конкретных подтипа абстрактного базового типа сообщения) и [ProtoInclude(...)]

Повторное расширение данных; Protobuf-net поддерживает , однако , как упоминается в блоге , не включено в текущую бета-версию v2. Это будет там в ближайшее время, но мне пришлось где-то поставить строку. Он включен в версию v1 (r282), хотя

Обратите внимание, что protobuf-net является лишь одной из нескольких реализаций C # / .NET. Формат проводника такой же, но вы также можете рассмотреть напрямую портированную версию . Если бы мне пришлось суммировать разницу, я бы сказал, что «protobuf-net - это сериализатор .NET, который оказывается protobuf; protobuf-csharp-port - это сериализатор protobuf, который оказывается .NET» - оба они достигают одного и того же конца, но Protobuf-net фокусируется на том, чтобы быть идиоматичным для C # /. NET, где порт больше ориентирован на использование того же API. Либо здесь должно работать, конечно.

...