Asp.net mvc 当可启动组件需要IBU时,Autofac IStartable能否与NServiceBus一起使用?
这里的场景是,有一个组件需要在启动时运行一些初始化代码。这是通过让代码实现Asp.net mvc 当可启动组件需要IBU时,Autofac IStartable能否与NServiceBus一起使用?,asp.net-mvc,autofac,nservicebus,bootstrapping,Asp.net Mvc,Autofac,Nservicebus,Bootstrapping,这里的场景是,有一个组件需要在启动时运行一些初始化代码。这是通过让代码实现Autofac.IStartable.Start并将代码注册为IStartable来实现的 然后,该代码被用于多种环境:两个ASP.NET网站、一个托管的NSB应用程序和一个基于Atlas的Windows服务。这两种方法都很有效 最近的一项更改为该启动代码引入了构造函数注入依赖项,其中包括NServiceBus.IBus的一个实例。当代码现在在NServiceBus主机内运行时,它会抛出一个ComponentNotRegi
Autofac.IStartable.Start
并将代码注册为IStartable
来实现的
然后,该代码被用于多种环境:两个ASP.NET网站、一个托管的NSB应用程序和一个基于Atlas的Windows服务。这两种方法都很有效
最近的一项更改为该启动代码引入了构造函数注入依赖项,其中包括NServiceBus.IBus
的一个实例。当代码现在在NServiceBus主机内运行时,它会抛出一个ComponentNotRegisteredException
声明“请求的服务'NServiceBus.IBus'尚未注册”
以下是NServiceBus主机(v4.7)的端点配置:
调用ContainerBuilder.Build()
方法时,似乎正在执行IStartable.Start
方法,这是可以理解的,但此时IBus
未在容器中注册
当稍后通过NServiceBus实例化消息处理程序时,如果这些处理程序依赖于IBus
,则正确注入总线。这将表明NServiceBus在容器生成后正在向容器“添加”新注册
我修改了启动代码以实现NServiceBus.iwanttorunhenbus启动和停止
,然后它在NServiceBus托管的应用程序中成功运行Start
方法。但是,Start
方法不会从ASP.NET应用程序或WindowsService执行
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();
builder.Register(cb => bus).As<IBus>().SingleInstance();
因此,我的双重问题是:Autofac.IStartable
是否仍能以某种方式在NServiceBus托管的应用程序中使用,或者是否有一种方法可以使另一种常见的启动/引导机制工作,例如NServiceBus.iwanttorunhenbus启动和停止
在NServiceBus托管的应用程序中,Autofac.IStartable
是否仍能以某种方式使用
是,但如果组件依赖于IBus
,则不会
NServiceBus.iwanttorunhenbus启动和停止
是否可以作为替代方案
仅当您在每个应用程序中处理NSB消息时。在我的例子中,web站点只向远程端点发送消息,因此没有调用此接口
我的“解决方案”是确保启动代码在两种情况下都能运行,这有两个方面:
首先,在需要在启动时运行的类上实现Autofac.IStartable
和NServiceBus.iwanttorunhenbus启动和停止
。它们具有相同的方法签名,这很方便
其次,仅在未调用NServiceBus.iwanttorunhenbusstartsandstops
的应用程序中,在容器中注册Autofac.IStartable
实现。这是通过将其注册拆分为单独的Autofac模块来实现的,该模块仅在这些应用程序中注册。该模块如下所示:
public class StartablesModule : Module
{
protected override void Load([NotNull] ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(
typeof (StartablesModule).Assembly)
.Where(t => t.IsAssignableTo<IStartable>())
.As<IStartable>();
}
}
公共类startableModule:模块
{
受保护的覆盖无效加载([NotNull]ContainerBuilder生成器)
{
builder.RegisterAssemblyTypes(
类型(StartablesModule.Assembly)
.Where(t=>t.IsAssignableTo())
.As();
}
}
在您的代码中,您似乎正在使用默认容器与NServiceBus,您不应该将容器传递给NServiceBus吗?在初始化NServiceBus主机的代码中,这是第一个代码片段,容器被传递给NServiceBus。初始化web应用程序总线的代码(片段编号2)仅在web应用程序可以向总线发送消息时才这样做。web应用中没有处理程序。我想这与为什么iwanttorunhenbusstartsandstops
在该实例中没有被触发有关。错过了!Web应用程序上的代码仍应执行iwanttorunhenbusstartsandstops
,唯一未执行的时间是如果端点配置为SendOnlyYes,则IBU仅在总线即将启动时在容器中注册,因此,IStartable
可能在您的场景中不起作用。在本例中,端点仅用于发送,尽管我没有明确地将其配置为发送。web应用程序没有处理程序。我想这就是为什么iwanttorunhenbusstartsandstops
不执行的原因。
public class StartablesModule : Module
{
protected override void Load([NotNull] ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(
typeof (StartablesModule).Assembly)
.Where(t => t.IsAssignableTo<IStartable>())
.As<IStartable>();
}
}