2015-03-16 1 views
1

Я работаю с кодом, который я еще не написал, и пытаюсь понять, почему конкретная функциональность не работает так, как я предполагаю. В частности, у меня есть три проекта в рамках моего решения:Как настроить NServiceBus для сканирования сборки для IMessage?

API 
Messages 
    Events 
Processors 

События - это папка в сообщениях. API будет взаимодействовать с процессорами, используя NServiceBus, через сообщения, определенные в Messages/Events. Каждый из классов в Messages/Events расширяет IMessage.

Теперь в файле конфигурации для шины, которая используется совместно обоими процессорами и API, я нашел эти строки:

var conventionsBuilder = config.Conventions(); 
conventionsBuilder.DefiningEventsAs(t => t.Namespace != null && t.Namespace.StartsWith("DE.STEP.Messages") && t.Namespace.EndsWith("Events")); 
return config; 

Это был осуществлен ранее, и классы внутри Messages/Events не распространяется IMessage на более ранний времени, вместо этого указанный выше код определял, где и какое сообщение может быть квалифицировано как. Теперь, поскольку я представил IMessage, я решил, что смогу удалить эти 3 строки кода. Однако, когда я это делаю, никакие сообщения никогда не попадают в мою очередь из API. Код, который пытается опубликовать это Bus.Publish<>();

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

EDIT: В соответствии с Документами NServiceBus

By default, NServiceBus scans all assemblies in the endpoint 
bin folder to find types implementing its interfaces so that 
it can configure them automatically. 

И Messages.dll появляется в bin обоих API и процессоров. Итак, поскольку Messages.dll содержит все мои IMessages, не должно ли поведение по умолчанию достаточно, чтобы сделать их доступными для публикации/подписки? То есть не следует ли снимать 3 строки, о которых идет речь, не имеет никакого эффекта?

+0

Вы пробовали 1) Внедрение 'IEvent' вместо' IMessage' и 2) Правильно ли настроены конечные точки сообщений? –

+0

Отображения конечных точек сообщений действительно правильные, как я сказал, с этими тремя строками, которые специально определяют, где искать сообщения, работает весь трубопровод. Я могу попробовать «IEvent», хотя я не понимаю, почему это работает над «IMessage», поскольку последнее является просто более широким определением, чем предыдущее. – mike

+0

. Если переход на IEvent не работает, можете ли вы поделиться своими сопоставлениями для одного события? Рассматривая правила маршрутизации событий и сообщений, кажется, что для каждого сообщения можно настроить только один маршрут, поскольку код не знает, является ли это командой или событием. Поэтому в случае сообщений он очищает все маршруты для сообщения и отслеживает только последний файл в этом типе. –

ответ

0

Иерархия события, если вы не используете ненавязчивый конфигурацию, должны быть следующими:

ConcreteEvent : IEvent : IMessage 

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

foreach (var mapping in messageEndpointMappings) 
{ 
    mapping.Configure((messageType, address) => 
    { 
     var conventions = context.Settings.Get<Conventions>(); 
     if (!(conventions.IsMessageType(messageType) || conventions.IsEventType(messageType) || conventions.IsCommandType(messageType))) 
     { 
      return; 
     } 

     if (conventions.IsEventType(messageType)) 
     { 
      router.RegisterEventRoute(messageType, address); 
      return; 
     } 

     router.RegisterMessageRoute(messageType, address); 
    }); 
} 

Conventions.IsEventType является поиск реализуется следующим образом:

EventsConventionCache.ApplyConvention(t, type => IsEventTypeAction(type)); 

Я не дам вам полный стек вызовов, но в основном, вы в конечном итоге здесь:

t => typeof(IEvent).IsAssignableFrom(t) && typeof(IEvent) != t 

Это будет оценивать, как false для конкретного события только реализующего IMessage, так RegisterEventRoute никогда не вызывается для вашего события, но скорее он будет рассматриваться как IMessage, который следует за различными правилами маршрутизации (только один маршрут на IMessage).

0

Короче говоря, вы должны иметь интерфейс IEvent в своем классе событий, чтобы иметь возможность использовать IBus.Publish, если вы не используете ненавязчивую конфигурацию.