2015-03-16 3 views
4

У меня есть приложение консоли, в котором вы можете указать параметры, в зависимости от параметров, которые будут загружены различными обработчиками. Например:Почему конфигурация NServiceBus повреждена после использования TypeToScan()

prgm.exe nyse 
prgm.exe nasdaq 

Цель состоит в том, что в моем коде я имею INyseHandlers и INasdaqHandlers и в первом случае загружается только любые обработчики, простирающиеся бывшие, аналогично для случая последних. Цель состоит в том, чтобы иметь одну программу, которая может прослушивать различные или все источники в зависимости от того, как она запускается. Для этого я установил свои интерфейсы, как указано выше. Тогда в моей конфигурации настройки:

var configuration = new BusConfiguration(); 
configuration.InitializeStepBusConventions(); // extension method, not the problem 

// Load all the handlers specified in command line arguments 
if (!Args.Contains("any") && Args.Length != 0) 
{ 
    List<Type> handlersToLoad = new List<Type>(); 

    foreach (var argument in Args) 
    { 
     Console.WriteLine("Adding {0} subscribers to loaded handlers. . .", argument.ToUpper()); 

     switch (argument) 
     { 
      case "nyse": 
       AddToHandlerList(handlersToLoad, typeof(INyseProcessor)); 
       break; 
      case "nasdaq": 
       AddToHandlerList(handlersToLoad, typeof(INasdaqProcessor)); 
       break;   
     } 
    } 

    configuration.TypesToScan(handlersToLoad); 
} 

configuration.UseContainer<NinjectBuilder>(c => c.ExistingKernel(Kernel)); 
configuration.EndpointName(ConfigurationManager.AppSettings[Defaults.Project.DefaultEndPointName]); 
NServiceBus.Logging.LogManager.Use<NLogFactory>(); 

Bus.Create(configuration).Start(); 

И где:

private void AddToHandlerList(List<Type> handlersToLoad, Type interfaceType) 
{ 
    List<Type> classesWhichExtendInterface = Assembly.GetExecutingAssembly().GetTypes().Where(t => interfaceType.IsAssignableFrom(t)).ToList(); 
    classesWhichExtendInterface.Remove(interfaceType); 

    handlersToLoad.AddRange(classesWhichExtendInterface); 
} 

Типы загружены, как и ожидалось, что List прекрасно. Но когда я запускаю это и добраться до Bus.Start линии я получаю следующее сообщение об ошибке:

The given key (NServiceBus.LocalAddress) was not present in the dictionary. 

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

EDIT: Вот метод расширения:

config.UseSerialization<JsonSerializer>(); 
config.UseTransport<RabbitMQTransport>(); 

config.UsePersistence<InMemoryPersistence>(); 
config.EnableInstallers(); 

return config; 
+0

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

+0

Я думаю, что это справедливое предположение, кажется, что 'TypeToScan' предполагает, что вы начинаете с нуля и полностью обрываете оставшиеся настройки по умолчанию. Любая идея, как я буду получать те, которые необходимы, чтобы сделать ее работоспособной? – mike

+1

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

ответ

5

Ваше исключение здесь происходит

localAddress = Address.Parse(Settings.Get<string>("NServiceBus.LocalAddress")); 

Настройки получить "NServiceBus.LocalAddress" КВП, установленный на транспорте. Поскольку вы не используете «ядро» транспорт (MSMQ), я мог бы подозревать, что ваши виды транспорта сборки должны быть включены в TypesToScan, из-за этого:

ForAllTypes<Feature>(TypesToScan, t => featureActivator.Add(t.Construct<Feature>())); 

У меня была аналогичная проблема с использованием транспорта SQL Server , когда я отправляю список сборок в «С» (сборки) и не включал сборки NServiceBus, транспорт не инициализировался. Как только я добавил сборки NServiceBus. *, Все приступило к работе.

+0

Я все еще немного смущен, у меня есть ссылки на 'NServiceBus.Transports.RabbitMQ', мне было интересно, если вы может немного расшириться? – mike

+0

Вам нужно получить типы из этой сборки и добавить их в свою коллекцию TypeToScan, например, этот handlersToLoad.AddRange (Assembly.GetAssembly (typeof (NServiceBus.Transports.RabbitMQ)). ExportedTypes) –

+0

Это кажется правильным направлением после загрузки следующее: 'handlersToLoad.AddRange (Assembly.Load (« NServiceBus.Transports.RabbitMQ »). GetTypes()); код больше не прерывается, однако желаемые обработчики никогда не выполняются, несмотря на то, что они были загружены. Должен ли я также загружать 'NServiceBus.Host' или' NServiceBus.Core'? – mike

0

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

Когда вы запускаете Test.Initialize, чтобы настроить ваш модульный тест, вы можете передать ему некоторую настройку BusConfiguration, в которой вы можете указать, какие сборки нужно сканировать. Я обычно использую следующий в качестве стандартной установки, которая предотвращает некоторые проблемы сборки загрузки, если вы отладку теста (по крайней мере, с NUnit):

Test.Initialize(conf => conf.AssembliesToScan(assembly.GetExecutingAssembly())) 

Однако по неизвестным причинам мне, сегодня я устанавливал до теста саги и получил ошибку NServiceBus.LocalAddress, упомянутую в этом вопросе. Мне удалось решить, что путем добавления дополнительного параметра в AssembliesToScan следующим образом:

Test.Initialize(conf => conf.AssembliesToScan(
      Assembly.GetExecutingAssembly(), 
      Assembly.GetCallingAssembly())); 

Надеется, что это помогает кому-то.

Смежные вопросы