这里的场景是有一个组件需要在启动时运行一些初始化代码。这是通过使代码实现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
?
答案 0 :(得分:1)
还是可以在NServiceBus托管的应用程序中以某种方式使用
Autofac.IStartable
吗?
是的,但如果组件依赖于IBus
,则不会。
可以
NServiceBus.IWantToRunWhenBusStartsAndStops
作为替代方案吗?
仅当您在每个应用程序中处理NSB消息时。就我而言,网站只向远程端点发送消息,因此未调用此接口。
我的解决方案&#39;确保启动代码在两种情况下运行都有两个方面:
首先,对需要在启动时运行的类实现Autofac.IStartable
和NServiceBus.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>();
}
}