zoukankan      html  css  js  c++  java
  • EasyNetQ笔记-替换IOC容器

    EasyNetQ是由独立组件的集合组成的。在内部,它使用了一个称为DefaultServiceProvider的微型内部DI(IoC)容器(EasyNetQ作者自己写的一个)。如果你看一下静态RabbitHutch类的代码(你用来创建IBus实例的那个),您将看到它只是创建了一个新的DefaultServiceProvider实例,注册所有EasyNetQ的组件,然后调用容器的Resolve() 方法,使用容器提供的依赖关系树创建一个IBus的新实例:

            //registerServices:外部通过此参数注册服务
            public static IBus CreateBus(Func<IServiceResolver, ConnectionConfiguration> connectionConfigurationFactory, Action<IServiceRegister> registerServices)
            {
                var container = new DefaultServiceContainer();
                RegisterBus(container, connectionConfigurationFactory, registerServices);
                return container.Resolve<IBus>();
            }
                
            public static void RegisterBus(IServiceRegister serviceRegister,
                                           Func<IServiceResolver, ConnectionConfiguration> connectionConfigurationFactory,
                                           Action<IServiceRegister> registerServices)
            {
                serviceRegister.Register(c =>
                {
                    var configuration = connectionConfigurationFactory(c);
                    configuration.SetDefaultProperties();
                    return configuration;
                });
    
                serviceRegister.RegisterDefaultServices();
                registerServices(serviceRegister);
            }
        public static class ServiceRegisterExtensions
        {
            /// <summary>
            ///     Registers the default EasyNetQ components
            /// </summary>
            /// <param name="serviceRegister">The register</param>
            public static void RegisterDefaultServices(this IServiceRegister serviceRegister)
            {
                Preconditions.CheckNotNull(serviceRegister, "container");
    
                // Note: IConnectionConfiguration gets registered when RabbitHutch.CreateBus(..) is run.
                // default service registration
                serviceRegister
                    .Register<IConnectionStringParser, ConnectionStringParser>()
                    .Register<ISerializer>(_ => new JsonSerializer())
                    .Register<IConventions, Conventions>()
                    .Register<IEventBus, EventBus>()
                    .Register<ITypeNameSerializer, DefaultTypeNameSerializer>()
                    .Register<ICorrelationIdGenerationStrategy, DefaultCorrelationIdGenerationStrategy>()
                    .Register<IMessageSerializationStrategy, DefaultMessageSerializationStrategy>()
                    .Register<IMessageDeliveryModeStrategy, MessageDeliveryModeStrategy>()
                    .Register(new AdvancedBusEventHandlers())
                    .Register<IProduceConsumeInterceptor, DefaultInterceptor>()
                    .Register<IConsumerDispatcherFactory, ConsumerDispatcherFactory>()
                    .Register<IExchangeDeclareStrategy, DefaultExchangeDeclareStrategy>()
                    .Register<IConsumerErrorStrategy, DefaultConsumerErrorStrategy>()
                    .Register<IErrorMessageSerializer, DefaultErrorMessageSerializer>()
                    .Register<IHandlerRunner, HandlerRunner>()
                    .Register<IInternalConsumerFactory, InternalConsumerFactory>()
                    .Register<IConsumerFactory, ConsumerFactory>()
                    .Register(c =>
                    {
                        var connectionConfiguration = c.Resolve<ConnectionConfiguration>();
                        return ConnectionFactoryFactory.CreateConnectionFactory(connectionConfiguration);
                    })
                    .Register<IClientCommandDispatcher, SingleChannelClientCommandDispatcher>()
                    .Register<IPersistentConnection, PersistentConnection>()
                    .Register<IPersistentChannelFactory, PersistentChannelFactory>()
                    .Register<IPublishConfirmationListener, PublishConfirmationListener>()
                    .Register<IHandlerCollectionFactory, HandlerCollectionFactory>()
                    .Register<IPullingConsumerFactory, PullingConsumerFactory>()
                    .Register<IAdvancedBus, RabbitAdvancedBus>()
                    .Register<IPubSub, DefaultPubSub>()
                    .Register<IRpc, DefaultRpc>()
                    .Register<ISendReceive, DefaultSendReceive>()
                    .Register<IScheduler, ExternalScheduler>()
                    .Register<IBus, RabbitBus>();
            }
    }
    

    但是如果您希望EasyNetQ使用您的选择容器呢?从版本0.25,RabbitHutch类提供了一个静态方法SetContainerFactory,它允许您注册一个可选的容器工厂方法,你想怎么实现EasyNetQ.IContainer接口都可以,只要通过该工厂方法提供给EasyNetQ即可。

    Jeff Doolittle已经为Windsor and Structure Map创造了IoC容器封装:

    https://github.com/jeffdoolittle/EasyNetQ.DI

    在这个例子中,我们使用了Castle Windsor IoC容器:

    // 注册我们替换的容器工厂
    RabbitHutch.SetContainerFactory(() =>
        {
            // 创建一个Windsor IoC容器实例
            var windsorContainer = new WindsorContainer();
    
            // 把Windsor封装到我们写的实现了EasyNetQ.IContainer接口的封装类对象中
            return new WindsorContainerWrapper(windsorContainer);
        });
    
    // 现在我们创建一个IBus接口的实例,但这次它是从windsor IoC容器中解析出来的,
    // 而不是像以前例子那样,从EasyNetQ默认的IoC容器了。
    var bus = RabbitHutch.CreateBus("host=localhost");
    

    下面是WindsorContainerWrapper类,我用来封装Windsor IoC容器的实例的,目的是实现EasyNetQ.IContainer接口,因为EasyNetQ里访问容器都是用的这个接口类型的实例(当然你也可以自己去写一个封装,爱封装啥IoC就去封装啥):

    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 方法,但是您可以通过Advanced Bus访问容器,这样清理Windsor:

    ((WindsorContainerWrapper)bus.Advanced.Container).Dispose();
    bus.Dispose();
    
  • 相关阅读:
    go 代理
    mongo创建用户
    博客搬家&留言板
    noip2020 SD选手迷惑行为大赏
    noip2020游记
    P4174 [NOI2006] 最大获利
    P3327 [SDOI2015]约数个数和
    P5069 [Ynoi2015]纵使日薄西山
    P3747 相逢是问候
    HDE6315 Naive Operations
  • 原文地址:https://www.cnblogs.com/fanfan-90/p/13622335.html
Copyright © 2011-2022 走看看