我在获得NServiceBus 4.6.1依赖注入与Saga超时工作时遇到问题。我在ASP中使用自托管。. NET web应用程序,并有属性注入设置。当从web控制器发送消息时,它可以工作,但是,当超时消息在saga中处理时,相同的DI属性没有被设置并且为空。
以下是设置的关键部分:
Global.asax.cs
public class MvcApplication : System.Web.HttpApplication
{
public static IWindsorContainer Container { get; private set; }
protected void Application_Start()
{
ConfigureIoC();
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
DeviceManagerDbInitializer.Instance.InitializeDatabase();
ConfigureNServiceBus();
}
protected void Application_End()
{
if (Container != null)
{
Container.Dispose();
}
}
private static void ConfigureIoC()
{
Container = new WindsorContainer()
.Install(FromAssembly.This());
var controllerFactory = new WindsorControllerFactory(Container.Kernel);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
GlobalConfiguration.Configuration.DependencyResolver
= new WindsorDependencyResolver(Container);
}
private void ConfigureNServiceBus()
{
Configure.ScaleOut(s => s.UseSingleBrokerQueue());
Configure.Instance.PeekInterval(500);
Configure.Instance.MaximumWaitTimeWhenIdle(2000);
Feature.Enable<TimeoutManager>();
Feature.Enable<Sagas>();
IStartableBus startableBus = Configure.With()
.DefineEndpointName("MyQueue")
.CastleWindsorBuilder(Container) //using NServiceBus CastleWindsor 4.6.1
.UseTransport<AzureStorageQueue>()
.UseAzureTimeoutPersister()
.AzureSagaPersister()
.PurgeOnStartup(false)
.UnicastBus()
.LoadMessageHandlers()
.RunHandlersUnderIncomingPrincipal(false)
.Log4Net(new DebugAppender { Threshold = Level.Warn })
.RijndaelEncryptionService()
.CreateBus();
Configure.Instance.ForInstallationOn<Windows>().Install();
startableBus.Start();
}
}
传奇类
public class MySaga: Saga<MySagaData>,
IAmStartedByMessages<StartMySagaCommand>,
IHandleMessages<SomeMessage>,
IHandleTimeouts<SomeTimeout>
{
public DependentService MyInjectedService {get; set;}
public override void ConfigureHowToFindSaga()
{
ConfigureMapping<StartMySagaCommand>( message => message.MyId).ToSaga( saga => saga.MyId );
ConfigureMapping<SomeMessage>( message => message.MyId).ToSaga( saga => saga.MyId );
ConfigureMapping<SomeTimeout>( message => message.MyId).ToSaga( saga => saga.MyId );
}
public void Handle(SomeMessage message)
{
// Here MyInjectedService is fine
MyInjectedService.DoSomething(message);
}
public void Timeout(SomeTimeout state)
{
// Here MyInjectedService is always null
MyInjectedService.DoSomething(state);
}
}
我已经尝试了这里,这里和这里的解决方案,但没有一个解决问题。
我找到了问题所在。依赖注入不能在Saga的超时处理程序中工作,因为Castle。温莎的生活方式设置为LifestylePerWebRequest,例如:
public class WindsorServicesInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register( Component.For<DependentService>()
.LifestylePerWebRequest() );
}
}
将Lifestyle改为LifeStyleTransient后,它开始起作用。任何其他"非web请求"的生活方式都应该在这里工作。
在我们的设置中,NServiceBus主机在web应用程序下运行,常规消息处理程序很好,因为它们是在控制器动作中调用的,例如:
[HttpPost]
public ActionResult DoSomething( int myId)
{
_bus.Send( "MyBus", new SomeMessage { MyId = something.MyId } );
return View();
}
当saga为此处理SomeMessage消息时,它必须仍然是web请求的一部分,并且Windsor照常解析依赖关系。然而,超时会在一段时间后被触发(在本例中是5分钟),因为它们不是web请求的一部分。Windsor不能解析DependentService对象,所以它保持为空。