当可启动组件需要IBus时,Autofac IStartable可以与NServiceBus一起使用吗?

时间:2015-02-02 18:19:16

标签: asp.net-mvc autofac nservicebus bootstrapping

这里的场景是有一个组件需要在启动时运行一些初始化代码。这是通过使代码实现Autofac.IStartable.Start并将代码注册为IStartable来实现的。

然后在几个上下文中使用此代码:一些ASP.NET网站,一个NServiceBus.Host.exe托管的NSB应用程序和一个基于Atlas的Windows服务。它在每个都很好。

最近的一项更改已将构造函数注入依赖项引入此启动代码,其中包含某些级别的NServiceBus.IBus实例。当代码现在在NServiceBus主机内部运行时,它会抛出ComponentNotRegisteredException声明"所请求的服务' NServiceBus.IBus'尚未注册。"

以下是NServiceBus主机(v4.7)的端点配置:

var builder = new ContainerBuilder();
builder.RegisterModule(new CoreModule());
Configure.With().AutofacBuilder(builder.Build());

似乎正在发生的事情是IStartable.Start方法在调用ContainerBuilder.Build()方法时执行,这是可以理解的,但此时IBus未在容器中注册。

稍后通过NServiceBus实例化消息处理程序,并且这些消息处理程序依赖于IBus时,会正确注入总线。这表明NServiceBus正在添加'在容器建成后对容器进行新的注册。

我已更改启动代码以实现NServiceBus.IWantToRunWhenBusStartsAndStops,然后在NServiceBus托管应用程序中成功运行Start方法。但是,然后不会从ASP.NET应用程序或WindowsService执行Start方法。

Web应用程序中的NServiceBus启动代码如下:

var bus = Configure.With((typeof (CoreModule).Assembly
    .GetTypes().Where(t =>
        t.Namespace != null
        && t.Namespace.StartsWith("OurApp.Messages"))))
    .DefaultBuilder()
    .DisableTimeoutManager()
    .UseTransport<Msmq>()
    .PurgeOnStartup(false)
    .UnicastBus()
    .CreateBus()
    .Start();

执行此代码,然后向容器构建器注册bus,如下所示:

builder.Register(cb => bus).As<IBus>().SingleInstance();

所以我的双重问题:可以在NServiceBus托管的应用程序中以某种方式使用Autofac.IStartable,或者是否有办法使替代的常见启动/引导机制工作,例如NServiceBus.IWantToRunWhenBusStartsAndStops

1 个答案:

答案 0 :(得分:1)

  

还是可以在NServiceBus托管的应用程序中以某种方式使用Autofac.IStartable吗?

是的,但如果组件依赖于IBus,则不会。

  

可以NServiceBus.IWantToRunWhenBusStartsAndStops作为替代方案吗?

仅当您在每个应用程序中处理NSB消息时。就我而言,网站只向远程端点发送消息,因此未调用此接口。

我的解决方案&#39;确保启动代码在两种情况下运行都有两个方面:

首先,对需要在启动时运行的类实现Autofac.IStartableNServiceBus.IWantToRunWhenBusStartsAndStops。它们具有相同的方法签名,这很方便。

其次,仅在调用Autofac.IStartable 的应用程序中注册容器中的NServiceBus.IWantToRunWhenBusStartsAndStops实现。这是通过将其注册拆分为单独的Autofac模块来完成的,该模块仅在这些应用程序中注册。该模块看起来像这样:

public class StartablesModule : Module
{
    protected override void Load([NotNull] ContainerBuilder builder)
    {
        builder.RegisterAssemblyTypes(
            typeof (StartablesModule).Assembly)
            .Where(t => t.IsAssignableTo<IStartable>())
            .As<IStartable>();
    }
}