NSeviceBus 6 - 如何使用Autofac将IMessageSession注入.Net Web API控制器?

时间:2016-12-16 16:02:31

标签: asp.net-web-api inversion-of-control autofac nservicebus

我使用NServiceBus 6,Autofac和.NET web api应用程序遇到了鸡蛋和鸡蛋的问题。根据NSB文件,NSB 6 does not automatically inject IMessageSession into a controller。当我在Startup.cs中进行端点配置时,我需要给它一个预先构建的容器,但是我还需要注册后来创建的端点。

Autofac抱怨使用Builder.Update()修改容器已经过时了。它有效,但我希望得到一些反馈,如果可能的话,更好的方法。

        var httpConfig = new HttpConfiguration();

        var builder = new ContainerBuilder();
        builder.RegisterAssemblyModules(Assembly.GetExecutingAssembly());
        builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();

        var container = builder.Build();
        httpConfig.DependencyResolver = new AutofacWebApiDependencyResolver(container);

        var config = new EndpointConfiguration("....");
        config.SendFailedMessagesTo("Error");
        //......
        config.SendOnly();
        config.UseContainer<AutofacBuilder>( customizations =>
                 {
                     customizations.ExistingLifetimeScope(container);
                 });

        var endpointInstance =  Endpoint.Start(config).GetAwaiter().GetResult();

        // This is now needed to get IMessageSession injected into the controller
        var builder = new ContainerBuilder();  
        builder.RegisterInstance(endpointInstance).As<IMessageSession>();

        // Autofac says Update is OBSOLETE and not to modify the 
        // container after it is built!
        builder.Update(container);

1 个答案:

答案 0 :(得分:2)

您可以在这里使用lambda注册。

首先,假设您有一个静态方法来创建端点。如果是这样,它将更容易显示示例。它看起来像这样:

public static IMessageSession CreateMessageSession(ILifetimeScope container)
{
  var config = new EndpointConfiguration("....");
  config.SendFailedMessagesTo("Error");
  //......
  config.SendOnly();
  config.UseContainer<AutofacBuilder>( customizations =>
             {
                 customizations.ExistingLifetimeScope(container);
             });

  return Endpoint.Start(config).GetAwaiter().GetResult();
}

注意我切换到使用ILifetimeScope而不是容器。

现在你可以这样做:

builder.Register(ctx => CreateMessageSession(ctx.Resolve<ILifetimeScope>()))
       .As<IMessageSession>()
       .SingleInstance();

通过使用SingleInstance,在lambda中解析的生命周期范围实际上将是根容器。事情会根据需要排列。

我认识到你可能需要/希望其他地方有EndpointConfiguration个对象。你仍然可以使用lambdas但是在对象上注册一个闭包。更改静态方法以接受端点配置和...

var endpointConfig = new EndpointConfiguration("....");
builder.Register(ctx => CreateMessageSession(endpointConfig, ctx.Resolve<ILifetimeScope>()))
       .As<IMessageSession>()
       .SingleInstance();
// Do further work with endpointConfig - lambda won't get called
// until you actually resolve IMessageSession so the closure is
// like a lazy bind.

即使您的要求更复杂,我认为对这样的对象进行lambdas和闭包将是您尝试更新构建容器的方法。