Rebus与简单的注射器打破变化

时间:2017-08-25 17:37:00

标签: c# asp.net-web-api simple-injector rebus

情景:

  • 使用多个卫星库的Web API应用程序
  • .NET Framework 4.6
  • 简单注射器
  • Rebus
  • Rebus.AzureServiceBus
  • Rebus.SimpleInjector

在我的应用程序中,有多个卫星库,其中大部分都有一个实现SimpleInjector IPackage接口的类,即将容器注册分组到不同的库中。这些包在Startup

注册
container.RegisterPackages(AppDomain.CurrentDomain.GetAssemblies());

其中一个软件包包含Rebus配置

IContainerAdapter adapter = new SimpleInjectorContainerAdapter( container );
Configure.With( adapter )
            .Transport( t => t.UseAzureServiceBusAsOneWayClient( connectionString, AzureServiceBusMode.Standard ) )
            .Routing( r =>
            r.TypeBased()
                .MapAssemblyOf<TransactionCreated>( "MyQueue" )
            )
            .Options( oc => {
                oc.SetNumberOfWorkers( 1 );
            } )
            .Start();

今天早上我们将Rebus软件包升级到以下版本:

  • Rebus 4.0.1
  • Rebus.AzureServiceBus 4.0.0
  • Rebus.SimpleInjector 4.0.0

升级后系统停止工作,现在我们收到以下错误

  

首次调用GetInstance后无法更改容器,   GetAllInstances和验证。请参阅   https://simpleinjector.org/locked了解容器的原因   锁定。以下堆栈跟踪描述了该位置   容器被锁定:

通过调试代码,我们可以看到另一个包在注册rebus之后注册,因此出错。我们可以确认代码没有进行任何修改,并且它与之前的版本一样正常工作。

我还可以确认,通过降级到这些版本,问题就会消失

  • Rebus 3.1.5
  • Rebus.AzureServiceBus 3.0.0
  • Rebus.SimpleInjector 3.0.0

有什么建议吗?

编辑:根据@Steven请求,我添加了完整的堆栈跟踪

  

描述:执行期间发生未处理的异常   当前的网络请求。请查看堆栈跟踪了解更多信息   有关错误的信息以及它在代码中的起源。

     

异常详细信息:System.InvalidOperationException:容器   第一次调用GetInstance,GetAllInstances后无法更改   和验证。请参阅https://simpleinjector.org/locked以了解相关信息   容器锁定的原因。以下堆栈跟踪描述了   容器被锁定的位置:

at Rebus.SimpleInjector.SimpleInjectorContainerAdapter.SetBus(IBus bus)   
at Rebus.Config.RebusConfigurer.Start()
at XXX.YYY.EndpointEvents.Producer.IOC.EndpointEventsProducerModule.RegisterServices(Container container) 
at SimpleInjector.PackageExtensions.RegisterPackages(Container container, IEnumerable assemblies)
at XXX.YYY.WebAPI.SimpleInjectorWebApiInitializer.InitializeContainer(Container container) 
at XXX.YYY.WebAPI.SimpleInjectorWebApiInitializer.Initialize() 
at XXX.YYY.WebAPI.Startup.Configuration(IAppBuilder app)
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at Owin.Loader.DefaultLoader.<>c__DisplayClass12.<MakeDelegate>b__b(IAppBuilder builder)
at Owin.Loader.DefaultLoader.<>c__DisplayClass1<LoadImplementation>b__0(IAppBuilder builder) 
at Microsoft.Owin.Host.SystemWeb.OwinHttpModule.<>c__DisplayClass2.<InitializeBlueprint>b__0(IAppBuilder builder) 
at Microsoft.Owin.Host.SystemWeb.OwinAppContext.Initialize(Action startup)
at Microsoft.Owin.Host.SystemWeb.OwinBuilder.Build(Action startup)
at Microsoft.Owin.Host.SystemWeb.OwinHttpModule.InitializeBlueprint()  
at System.Threading.LazyInitializer.EnsureInitializedCore[T](T& target, Boolean& initialized, Object& syncLock, Func valueFactory)  
at Microsoft.Owin.Host.SystemWeb.OwinHttpModule.Init(HttpApplication context)  
at System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers)
at System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context)
at System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context)
at System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext)

3 个答案:

答案 0 :(得分:3)

对于迟到对这个问题的反应抱歉:)

我终于有时间了解SimpleInjector是如何进行容器注册的,并了解Rebus配置API如何以某种方式倾向于以这种方式工作。

事实证明,通常

Configure.With(new MyFavoriteContainerAdapter(container))
    .(...)
    .Start();

spell必须以某种方式移动到Func<IBus>,这样才能在实际启动总线之前完成所有与Rebus相关的注册(以及你自己的注册)。

结果(刚刚在NuGet.org上的Rebus.SimpleInjector 5.0.0-b01中出现)就是这个API:

public class RebusPackage : IPackage
{
    public void RegisterServices(Container container)
    {
        Console.WriteLine("Calling RebusPackage");

        container.ConfigureRebus(
            configurer => configurer
                .Transport(t => t.UseInMemoryTransport(new InMemNetwork(), "test"))
                .Start()
        );

    }
}

如果您正在使用SimpleInjector.Packaging,或者只是

,它的外观如何
container.ConfigureRebus(
    configurer => configurer
        .Transport(t => t.UseInMemoryTransport(new InMemNetwork(), "test"))
        .Start()
);

如果您拥有的只是一个SimpleInjector container

当你认为是时候开始公共汽车时,你要么

container.StartBus();

或等到IBus解决后。

答案 1 :(得分:2)

正如您所看到的那样here添加了新的编码以确保总线处理,这引入了一个问题,您的代码似乎很好,只需要等待修复。在新线下面

 +            // cheat and activate the IBus singleton behind the scenes, thus ensuring that the container will dispose it when it is time
 +            var registration = _container.GetRegistration(typeof(IBus));
 +  +            registration.GetInstance();
 +

答案 2 :(得分:0)

您的EndpointEventsProducerModule正在呼叫RebusConfigurer.Start。开始从容器中解析IBus

由于可以按任何顺序调用模块,因此只应在模块中进行注册。移除Start电话并在调用container.Verify()后调用它。