Устранена проблема: в MSMQ версии 3 или ниже (в системах, таких как Windows XP, Windows Server 2003), вложенные очереди не поддерживаются, и поэтому Rhino SB использует FlatQueueStrategy для управления очередями.Проблемы возникают при настройке контейнера объекта Spring.Конкретно, в классе Rhino.ServiceBus.Spring.SpringBuilder есть два места, где необходимо внести изменения.
1) метод RegisterMsmqTransport :
if (queueStrategyType.GetConstructor(new[] { typeof(IQueueStrategy), typeof(Uri) }) != null)
{
applicationContext.RegisterSingleton(queueStrategyType, typeof (IQueueStrategy).FullName, applicationContext.Get<IEndpointRouter>(), config.Endpoint);
}
else
{
// use default
applicationContext.RegisterSingleton(queueStrategyType);
}
второйчасть оператора if вызывается всегда, потому что FlatQueueStrategy не имеет конструктора с параметрами типа IQueueStrategy и Uri.Но у него даже нет конструктора без параметров.Поэтому FlatQueueStrategy неправильно зарегистрирован в контейнере объекта.Модификация для этой части:
if (queueStrategyType.GetConstructor(new[] { typeof(IEndpointRouter), typeof(Uri) }) != null)
{
applicationContext.RegisterSingleton(queueStrategyType, typeof (IQueueStrategy).FullName, applicationContext.Get<IEndpointRouter>(), config.Endpoint);
}
else
{
// use default
applicationContext.RegisterSingleton(queueStrategyType);
}
2) метод RegisterDefaultServices
Следующая проблема в методе RegisterDefaultServices:
applicationContext.RegisterSingleton<IServiceLocator>(() => new SpringServiceLocator(applicationContext));
applicationContext.RegisterSingletons<IBusConfigurationAware>(typeof(IServiceBus).Assembly);
foreach (var busConfigurationAware in applicationContext.GetAll<IBusConfigurationAware>())
{
busConfigurationAware.Configure(config, this); // here is the method RegisterMsmqTransport called
}
foreach (var module in config.MessageModules)
{
applicationContext.RegisterSingleton(module, module.FullName);
}
applicationContext.RegisterSingleton<IReflection>(() => new DefaultReflection());
applicationContext.RegisterSingleton(config.SerializerType);
applicationContext.RegisterSingleton<IEndpointRouter>(() => new EndpointRouter());
метод RegisterMsmqTransport вызывается до того, как IEndpointRouter будет зарегистрирован в контейнере объекта.IEndpointRouter используется в методе RegisterMsmqTransport (см. 1), и поэтому вызов метода
applicationContext.Get<IEndpointRouter>()
создает исключение.Модификация здесь будет:
applicationContext.RegisterSingleton<IServiceLocator>(() => new SpringServiceLocator(applicationContext));
applicationContext.RegisterSingletons<IBusConfigurationAware>(typeof(IServiceBus).Assembly);
applicationContext.RegisterSingleton<IReflection>(() => new DefaultReflection());
applicationContext.RegisterSingleton<IEndpointRouter>(() => new EndpointRouter());
foreach (var busConfigurationAware in applicationContext.GetAll<IBusConfigurationAware>())
{
busConfigurationAware.Configure(config, this);
}
foreach (var module in config.MessageModules)
{
applicationContext.RegisterSingleton(module, module.FullName);
}
applicationContext.RegisterSingleton(config.SerializerType);