Проблема сериализации Nservicebus производных типов

для настройки контекста я обмениваюсь сообщениями между моим клиентом nServiceBus и сервером nSerivceBus. это пространство имен xyz.Messages и класс Message: IMessage

У меня есть больше сообщений, которые находятся в других dll, таких как xyz.Messages.Domain1, xyz.Messages.Domain2, xyz.Messages.Domain3. и сообщения, которые выводятся из этого базового сообщения, Message.

У меня есть конечные точки, определенные как:

 at client
<UnicastBusConfig>
 <MessageEndpointMappings>
    <add Messages="xyz.Messages" Endpoint="xyzServerQueue" />
    <add Messages="xyz.Messages.Domain1" Endpoint="xyzServerQueue" />
    <add Messages="xyz.Messages.Domain2" Endpoint="xyzServerQueue" />
  </MessageEndpointMappings>
</UnicastBusConfig>

на сервере

<UnicastBusConfig>
 <MessageEndpointMappings>
   <add Messages="xyz.Messages" Endpoint="xyzClientQueue" />
   <add Messages="xyz.Messages.Domain1" Endpoint="xyzClientQueue" />
   <add Messages="xyz.Messages.Domain2" Endpoint="xyzClientQueue" />
 </MessageEndpointMappings>
</UnicastBusConfig>

и шина инициализирована как

        IBus serviceBus = Configure.With()
            .SpringBuilder()
            .XmlSerializer()
            .MsmqTransport()
            .UnicastBus()
            .LoadMessageHandlers()
            .CreateBus()
            .Start();

теперь, когда я пытаюсь отправить экземпляр типа Message или любого производного типа Message, он успешно отправляет сообщение на сервер и на сервер, я получаю правильный тип.

eg.

Message message= new Message();
Bus.Send(message); // works fine, transfers Message type
message = new MessageDerived1();
Bus.Send(message); // works fine, transfers MessageDerived1 type
message = new MessageDerived2();
Bus.Send(message); // works fine, transfers MessageDerived2 type

Моя проблема возникает, когда какой-либо тип, скажем, MessageDerived1, содержит переменную-член типа Message, и когда я присваиваю ее производному типу, тип не передается должным образом по сети. Он передается только как тип сообщения, а не производный тип.

public class MessageDerived2 : Message
{
  public Message message;
}

MessageDerived2 messageDerived2= new MessageDerived2();
messageDerived2.message = new MessageDerived1();
message = messageDerived2;
Bus.Send(message); // incorrect behaviour, transfers MessageDerived2 correctly, but looses type of  MessageDerived2.Message (it deserializes as Message type, instead of MessageDerived1)

любая помощь приветствуется.

Спасибо, ТиДжей.


person Tiju John    schedule 12.05.2010    source источник


Ответы (2)


NServiceBus XmlSerializer не поддерживает это — см. ветку по адресу http://tech.groups.yahoo.com/group/nservicebus/message/6549

BinarySerializer будет работать, или вы можете реализовать собственный сериализатор сообщений. На мой взгляд, DataContractSerializer должен быть доступен из коробки для сценариев сериализации, которые XmlSerializer не обрабатывает.

Обратите внимание, что, сделав это, вы, вероятно, потеряете поддержку версий сообщений NSB - если это важно для вас, я бы предложил переосмыслить дизайн вашего сообщения.

person Sam    schedule 20.05.2010

Вот ответ Уди

Во-первых, крайне необычно, чтобы клиентские очереди отображались в конфигурации сервера. Я бы рекомендовал удалить это.

Во-вторых, я предполагаю, что вы не используете универсальный хост, поскольку вы вручную инициализируете шину - это нормально, просто хотел проверить. Кроме того, вы используете один и тот же код для инициализации как на стороне клиента, так и на стороне сервера? Это особенно не рекомендуется. По крайней мере, серверная часть должна быть транзакционной (если только вы не используете какой-то идемпотентный маршрут обмена сообщениями).

В-третьих, то, что вы пытаетесь сделать, должно работать нормально, если вы используете двоичный сериализатор. Причина в предположении о более тесной связи и меньшей необходимости в явных контрактах сообщений. XML-сериализатор, с другой стороны, создан для обеспечения более явной схемы сообщений, поэтому не поддерживает такие виды производных типов.

Сценарии, в которых вы можете захотеть использовать производные типы в своих сообщениях (запросы, прямое манипулирование данными и т. д.), обычно являются областями, в которых вам не следует использовать обмен сообщениями с самого начала.

Надеюсь, что это поможет в некотором роде.

-- Уди Дахан

person Tiju John    schedule 17.06.2010