18,EasyNetQ-使用替代DI容器

EasyNetQ由獨立組件組成。 它在內部使用稱爲DefaultServiceProvider的小型內部DI(IoC)容器。 若是您查看用於建立核心IBus接口實例的靜態RabbitHutch類的代碼,您將看到它僅建立一個新的DefaultServiceProvider,註冊全部EasyNetQ組件,而後調用container.Resolve()建立一個 IBus的新實例及其由容器提供的依賴關係樹:git

public static IBus CreateBus(IConnectionConfiguration connectionConfiguration, Action<IServiceRegister> registerServices)
{
    Preconditions.CheckNotNull(connectionConfiguration, "connectionConfiguration");
    Preconditions.CheckNotNull(registerServices, "registerServices");

    var container = createContainerInternal();
    if (container == null)
    {
        throw new EasyNetQException("Could not create container. " + 
            "Have you called SetContainerFactory(...) with a function that returns null?");
    }

    registerServices(container);
    container.Register(_ => connectionConfiguration);
    ComponentRegistration.RegisterServices(container);

    return container.Resolve<IBus>();
}

可是若是你想讓EasyNetQ使用你選擇的容器呢? 從版本0.25開始,RabbitHutch類提供了一個靜態方法SetContainerFactory,它容許您註冊一個替代的容器工廠方法,該方法提供您所關心的EasyNetQ.IContainer的任何實現。github

Jeff Doolittle在這裏爲Windsor和Structure Map建立了容器包裝:https://github.com/jeffdoolittle/EasyNetQ.DIapp

在這個例子中,咱們使用Castle Windsor IoC容器:ide

//註冊咱們的替代容器工廠
RabbitHutch.SetContainerFactory(() =>
    {
        //建立一個Windsor的實例
        var windsorContainer = new WindsorContainer();

        //將它包裝在EasyNetQ.IContainer的實現中
        return new WindsorContainerWrapper(windsorContainer);
    });

// 如今咱們能夠建立一個IBus實例,但它是從windsor解決的,而不是EasyNetQ的默認服務提供者。
var bus = RabbitHutch.CreateBus("host=localhost");

這裏是WindsorContainerWrapper:this

public class WindsorContainerWrapper : IContainer, IDisposable
{
    private readonly IWindsorContainer windsorContainer;

    public WindsorContainerWrapper(IWindsorContainer windsorContainer)
    {
        this.windsorContainer = windsorContainer;
    }

    public TService Resolve<TService>() where TService : class
    {
        return windsorContainer.Resolve<TService>();
    }

    public IServiceRegister Register<TService>(System.Func<IServiceProvider, TService> serviceCreator) 
        where TService : class
    {
        windsorContainer.Register(
            Component.For<TService>().UsingFactoryMethod(() => serviceCreator(this)).LifeStyle.Singleton
            );
        return this;
    }

    public IServiceRegister Register<TService, TImplementation>() 
        where TService : class 
        where TImplementation : class, TService
    {
        windsorContainer.Register(
            Component.For<TService>().ImplementedBy<TImplementation>().LifeStyle.Singleton
            );
        return this;
    }

    public void Dispose()
    {
        windsorContainer.Dispose();
    }
}

請注意,全部EasyNetQ服務都應註冊爲singletons。spa

正確處理Windsor是很是重要的。 EasyNetQ不會在IContainer上提供Dispose方法,但您能夠經過高級總線訪問容器(是的,這也是新的),並以這種方式處置windsor:code

((WindsorContainerWrapper)bus.Advanced.Container).Dispose();
bus.Dispose();
相關文章
相關標籤/搜索