使用没有global.asax的structuremap注入NServiceBus

时间:2013-01-10 11:08:57

标签: asp.net-mvc-4 dependency-injection asp.net-web-api structuremap nservicebus

我是NServiceBus的新手,并且正在努力使用结构图在我的控制器中注入IBus。实际上在做了一点研究之后我发现我们可以通过将下面的代码放在global.asax的Application_Start事件中来注入它 -

protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        Configure.With()
                 .Log4Net()
                 .StructureMapBuilder()
                 .XmlSerializer()
                 .MsmqTransport()
                 .IsTransactional(false)
                 .PurgeOnStartup(false)
                 .UnicastBus()
                 .ImpersonateSender(false)
                 .CreateBus();
    }

在我的控制器中我可以使用IBus作为属性或构造函数注入:

private IBus Bus { get; set; }
    private ITest Test { get; set; }

    public MyLinkController(IBus bus, ITest test)
    {
        Bus = bus;
        Test = test;
    }

这很好,并且没有任何问题地注入总线。但我的问题是我无法控制global.asax,所以我想将配置放在其他地方,例如我尝试将它放在结构图注册表中,如下所示:

For<IBus>().Use(
            () =>
                NServiceBus.Configure.With()
                                         .Log4Net()
                                         .StructureMapBuilder()
                                         .XmlSerializer()
                                         .IsTransactional(true)
                                         .PurgeOnStartup(false)
                                         .UnicastBus()
                                         .ImpersonateSender(false)
                                         .CreateBus()
                                         .Start()
                );

但它没有帮助。看起来结构图需要在自己的初始化之前知道配置。 那么有没有办法在没有application_start事件的情况下做到这一点?

1 个答案:

答案 0 :(得分:3)

我能够通过结构图本身来做到这一点。这就是我改变结构图注册表的方法:

public ServiceBusRegistry()
    {
        ForSingletonOf<IBus>().Use(
            NServiceBus.Configure.With()
                       .Log4Net()
                       .DefaultBuilder()
                       .XmlSerializer()
                       .MsmqTransport()
                       .IsTransactional(false)
                       .PurgeOnStartup(false)
                       .UnicastBus()
                       .ImpersonateSender(false)
                       .CreateBus()
                       .Start()
            );
    }

将它放在结构图的Registry类中后,我可以在我的控制器中注入IBus:

public MyController(IRepository<Test, int> repository, IBus bus)
    {
        _repository = repository;
        _bus = bus;
    }

注意,这里我使用DefaultBuilder而不是StructureMapBuilder。我可能会在将来进一步改进它,但到目前为止它对我来说很好。

更新(在我们的项目设计更改后):

现在我们在API项目中有一个启动类(该项目是ASP.NET web API)虽然我们不使用global.asax的Application_start,但我们可以将启动代码放在这个启动类中:

[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(WebApiPreStartup), "Start", Order = -999)] //make sure we are first

namespace ADP.DS.FrontOffice.Quoting.WebApi
{
    public static class WebApiPreStartup
    {
        public static void Start()
        {
            GlobalFilterConfig.Configure(GlobalConfiguration.Configuration);
            BusConfig.Init();
        }
    }
}

并且配置在单独的类中:

public static void Init()
    {
        Configure.Serialization.SystemXml();
        Configure.ScaleOut(s => s.UseSingleBrokerQueue());
        var configUnicastBus = Configure.With()
            .StructureMapBuilder(ObjectFactory.Container)
            .UseTransport<NServiceBus.RabbitMQ>()
            .PurgeOnStartup(false)
            .UnicastBus();
        configUnicastBus.SendOnly();
    }