【问题标题】:NServiceBus Dependency Injection not working for Saga TimeoutsNServiceBus 依赖注入不适用于 Saga 超时
【发布时间】:2014-05-29 16:44:19
【问题描述】:

我在让 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);
    }

}

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

【问题讨论】:

  • 嗨,克里斯,您好像缺少配置如何查找 saga?你也有传奇数据中的独特属性吗?
  • 肖恩,感谢您的想法,但我刚刚将查找代码排除在示例之外,因为处理程序都被正确调用。问题在于,当调用 Timeout 处理程序时,NServiceBus 没有像常规 Handle 方法那样实例化 MyInjectedService DI 属性。
  • 有机会上传代码吗?还是在 Dropbox 上私下分享?我的电子邮件是 s.farmar 在 gmail
  • 不幸的是,这是我无法按原样共享的更大应用程序的一部分。我需要先创建一个精简版。
  • 如果您能做到,我很乐意为您提供帮助...

标签: nservicebus


【解决方案1】:

我在这里发现了问题。依赖注入在 Saga 的超时处理程序中不起作用,因为 Castle.Windsor 生活方式设置为 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 会正常解决依赖关系。但是,超时会在一段时间后(在本例中为五分钟)触发,因为它们不是 Web 请求的一部分。 Windsor 无法解析 DependentService 对象并且它保持为空。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 2012-12-31
    • 1970-01-01
    • 2017-06-16
    • 1970-01-01
    • 2019-09-11
    • 1970-01-01
    相关资源
    最近更新 更多