zoukankan      html  css  js  c++  java
  • ABP之事件总线(5)

    前面已经对Castle Windsor的基本使用进行了学习,有了这个基础,接下来我们将把我们的事件总线再次向ABP中定义的事件总线靠近。从源码中可以知道在ABP中定义了Dictionary,存放三种类型的Factory,然后通过容器的方式实例化相应的handlerfactory。承接前面的随笔,我们为什么要使用IOC?

    IOC是用来代替反射的。那么反射在我们EventBus中有什么功能?反射是用来创建handler的实例的。那么我们的容器其实就是用来初始化实例这么一点功能的,所以我们不需要过多的改动我们以前的代码,只需加入容器的注入,同时在初始化的时候将反射的方式改为容器的方式。

    IOCEventBus(第一种)

    using Castle.MicroKernel.Registration;
    using Castle.Windsor;
    using System;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace EventBus
    {
        public class IOCEventBus : IEventBus
        {
            private IOCEventBus()
            {
                IocContainer = new WindsorContainer();
                mapDic = new ConcurrentDictionary<Type, List<Type>>();
              
            }
            //EventBus单例模式
            public static IOCEventBus Default = new IOCEventBus();
            public IWindsorContainer IocContainer { get; private set; }
            private ConcurrentDictionary<Type, List<Type>> mapDic;
            public void Register<TEventData>(Type handlerType) where TEventData : IEventData
            {
                //将数据存储到mapDic
                var dataType = typeof(TEventData);
                Register(dataType, handlerType);
            }
            public void Register(Type dataType, Type handlerType)
            {
                //注册IEventHandler<T>到IOC容器
                var handlerInterface = handlerType.GetInterface("IEventHandler`1");
                if (!IocContainer.Kernel.HasComponent(handlerInterface))
                {

                   IocContainer.Register(Component.For(handlerInterface).ImplementedBy(handlerType));

                }
                //放入总线中
                if (mapDic.Keys.Contains(dataType))
                {
                    if (!mapDic[dataType].Contains(handlerType))
                    {
                        mapDic[dataType].Add(handlerType);
                    }
                }
                else
                {
                   
                    mapDic[dataType] = new List<Type>() { handlerType };
                   
                }
            }
            //取消注册只是取消EventBus中的事件处理,并不需要处理容器,所以代码相同
            public void Unregister<TEventData>(Type handler) where TEventData : IEventData
            {
                var dataType = typeof(TEventData);
                Unregister(dataType, handler);
            }
    
            public void Unregister(Type eventType, Type handler)
            {
    
                if (mapDic.Keys.Contains(eventType))
                {
                    if (mapDic[eventType].Contains(handler))
                    {
                        mapDic[eventType].Remove(handler);
                    }
                }
            }
            /// <summary>
            /// 触发调用处理事件
            /// </summary>
            /// <typeparam name="TEventData"></typeparam>
            /// <param name="eventData"></param>
            public void Trigger<TEventData>(TEventData eventData) where TEventData : IEventData
            {
                // var dataType = typeof(TEventData);
                var dataType = eventData.GetType();
                var handlerTypes = mapDic[dataType];
                foreach (var handlerType in handlerTypes)
                {
    
                    //从Ioc容器中获取所有的实例
                    var handlerInterface = handlerType.GetInterface("IEventHandler`1");
                    var eventHandlers = IocContainer.ResolveAll(handlerInterface);
    
                    //循环遍历,仅当解析的实例类型与映射字典中事件处理类型一致时,才触发事件
                    foreach (var eventHandler in eventHandlers)
                    {
                        if (eventHandler.GetType() == handlerType)
                        {
                            var handler = eventHandler as IEventHandler<TEventData>;
                            handler?.Handle(eventData);
                        }
                    }
               
                }
            }
        }
    
    }

    IOC(第二种)

    using Castle.MicroKernel.Registration;
    using Castle.Windsor;
    using System;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace EventBus
    {
        public class IOCEventBus : IEventBus
        {
            private IOCEventBus()
            {
                IocContainer = new WindsorContainer();
                mapDic = new ConcurrentDictionary<Type, List<Type>>();
              
            }
            //EventBus单例模式
            public static IOCEventBus Default = new IOCEventBus();
            public IWindsorContainer IocContainer { get; private set; }
            private ConcurrentDictionary<Type, List<Type>> mapDic;
            public void Register<TEventData>(Type handlerType) where TEventData : IEventData
            {
                //将数据存储到mapDic
                var dataType = typeof(TEventData);
                Register(dataType, handlerType);
            }
            public void Register(Type dataType, Type handlerType)
            {
                //注册IEventHandler<T>到IOC容器
                var handlerInterface = handlerType.GetInterface("IEventHandler`1");
                if (!IocContainer.Kernel.HasComponent(handlerInterface))
                {

                    IocContainer.Register(
                          Component.For(handlerInterface, handlerType));

    
                }
                //放入总线中
                if (mapDic.Keys.Contains(dataType))
                {
                    if (!mapDic[dataType].Contains(handlerType))
                    {
                        mapDic[dataType].Add(handlerType);
                    }
                }
                else
                {
                   
                    mapDic[dataType] = new List<Type>() { handlerType };
                   
                }
            }
            //取消注册只是取消EventBus中的事件处理,并不需要处理容器,所以代码相同
            public void Unregister<TEventData>(Type handler) where TEventData : IEventData
            {
                var dataType = typeof(TEventData);
                Unregister(dataType, handler);
            }
    
            public void Unregister(Type eventType, Type handler)
            {
    
                if (mapDic.Keys.Contains(eventType))
                {
                    if (mapDic[eventType].Contains(handler))
                    {
                        mapDic[eventType].Remove(handler);
                    }
                }
            }
            /// <summary>
            /// 触发调用处理事件
            /// </summary>
            /// <typeparam name="TEventData"></typeparam>
            /// <param name="eventData"></param>
            public void Trigger<TEventData>(TEventData eventData) where TEventData : IEventData
            {
                // var dataType = typeof(TEventData);
                var dataType = eventData.GetType();
                var handlerTypes = mapDic[dataType];
                foreach (var handlerType in handlerTypes)
                {
    
                    var eventHandler = IocContainer.Resolve(handlerType);
                    var handler = eventHandler as IEventHandler<TEventData>;
                    handler.Handle(eventData);
    
                }
            }
        }
    
    }

     上面的代码都是可以正常运行,其实上面的两种方式只是代码上书写的区别,主要是注入的方式不同,导致代码书写的方式不同

    第一种方式Tigger的时候比多,效率比较低,第二种方式代码较少,同时效率较高,但是向容器注入的类型比较多。Component.For方法上的使用还是很有意思的,第二种种方式直接向For的方法中传入了接口和类两个参数,而这个方法的作用,就是为传入的类型创建注入实例的,所以会在容器中注入接口和类。所以在后面Trigger的时候可以直接通过类的类型直接获取到实例。For方法最终在源码中会调用AddService

    上面的事件总线只是简单实现了基本的功能,基本上就是ABP事件总线的最最简单的模型,到此为止,事件总线的学习结束。

  • 相关阅读:
    [剑指 Offer 11. 旋转数组的最小数字]
    进程描述符(PCB)
    [剑指 Offer 57. 和为s的两个数字]
    Linux netstat命令
    kafka2.3.X配置文件
    docker
    shell操作mysql数据库
    Linux文件查找之find命令
    sed 切割日志文件
    Linux文本处理之awk
  • 原文地址:https://www.cnblogs.com/XZhao/p/9012716.html
Copyright © 2011-2022 走看看