18,EasyNetQ-使用替代DI容器
EasyNetQ由独立组件组成。 它在内部使用称为DefaultServiceProvider的小型内部DI(IoC)容器。 如果您查看用于创建核心IBus接口实例的静态RabbitHutch类的代码,您将看到它仅创建一个新的DefaultServiceProvider,注册所有EasyNetQ组件,然后调用container.Resolve()创建一个 IBus的新实例及其由容器提供的依赖关系树:
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的任何实现。
Jeff Doolittle在这里为Windsor和Structure Map创建了容器包装:https://github.com/jeffdoolittle/EasyNetQ.DI
在这个例子中,我们使用Castle Windsor IoC容器:
//注册我们的替代容器工厂 RabbitHutch.SetContainerFactory(() => { //创建一个Windsor的实例 var windsorContainer = new WindsorContainer(); //将它包装在EasyNetQ.IContainer的实现中 return new WindsorContainerWrapper(windsorContainer); }); // 现在我们可以创建一个IBus实例,但它是从windsor解决的,而不是EasyNetQ的默认服务提供者。 var bus = RabbitHutch.CreateBus("host=localhost");
这里是WindsorContainerWrapper:
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。
正确处理Windsor是非常重要的。 EasyNetQ不会在IContainer上提供Dispose方法,但您可以通过高级总线访问容器(是的,这也是新的),并以这种方式处置windsor:
((WindsorContainerWrapper)bus.Advanced.Container).Dispose();
bus.Dispose();
学习永不止境,技术成就梦想。