NServiceBus依赖注入不适用于Saga Timeouts

时间:2014-05-29 16:44:19

标签: nservicebus

我在使用Saga超时时遇到NServiceBus 4.6.1依赖注入问题。我在ASP.NET Web应用程序中使用自托管并具有属性注入设置。它可以在从Web控制器发送消息时起作用,但是,当在saga中处理Timeout消息时,相同的DI属性未被设置且为null。

以下是设置的关键部分:

的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);
    }

}

我尝试过找到hereherehere的解决方案,但没有一个解决了这个问题。

1 个答案:

答案 0 :(得分:2)

我在这里想出了问题。由于Castle.Windsor生活方式设置为LifestylePerWebRequest,因此依赖注入在Saga的超时处理程序中无效,例如:

public class WindsorServicesInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register( Component.For<DependentService>()
                                         .LifestylePerWebRequest() );
    }
}

将Lifestyle更改为LifeStyleTransient后,它开始工作。任何其他非网络请求&#39;生活方式也应该在这里发挥作用。

在我们的设置中,NServiceBus主机在Web应用程序下运行,并且常规消息处理程序很好,因为它们是在控制器操作中调用的,例如:

[HttpPost]
public ActionResult DoSomething( int myId)
{
    _bus.Send( "MyBus", new SomeMessage { MyId = something.MyId } );
     return View();
}

当saga为此处理SomeMessage消息时,它仍然必须是Web请求的一部分,Windsor会正常解析依赖关系。但是,超时会在一段时间后触发(在这种情况下为五分钟),它们不是Web请求的一部分。 Windsor无法解析DependentService对象,它保持为null。