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

    事件总线就是订阅/发布模式的一种实现    事件总线就是为了降低耦合

    1.比如在winform中  到处都是事件 

    触发事件的对象  sender

    事件的数据    e

    事件的处理逻辑  方法体

    通过EventBus实现事件对象和处理逻辑的解耦

    1.抽离事件对象    发生时间的事件   触发事件的对象源(可选)

        //
        // 摘要:
        //     Defines interface for all Event data classes.
        public interface IEventData
        {
            //
            // 摘要:
            //     The time when the event occured.
            DateTime EventTime { get; set; }
            //
            // 摘要:
            //     The object which triggers the event (optional).
            object EventSource { get; set; }

     2.抽离事件的处理对象

        public interface IEventHandler
        {
        }
        public interface IEventHandler<in TEventData> : IEventHandler
        {
            /// <summary>
            /// Handler handles the event by implementing this method.
            /// </summary>
            /// <param name="eventData">Event data</param>
            void HandleEvent(TEventData eventData);
        }

    3.所有EventData跟EventHandler不再耦合  全都跟EventBus进行通信

     在EventBus中有一个字典进行存放 EventData类型跟需要触发的Handler对象   

    这里的Type就是EventData       List<IEventHandlerFactory>>就是存放处理当前EventData的多个Handler

     private readonly ConcurrentDictionary<Type, List<IEventHandlerFactory>> _handlerFactories;

    4.ABP的EventBus封装的比较高深     自己来个简洁版    思想是一样的(这里还存在很多问题   比如并发  往字典存放数据没有加锁等问题  具体的看ABP)

    ABP初始化的时候会把所有的EventData和EventHandler对应存放到字典中   也可以通过Unregister移除某一个Handler

        public class EventBus : IEventBus
        {
            public EventBus()
            {
                mapDic = new ConcurrentDictionary<Type, List<Type>>();
            }
            //EventBus单例模式
            public static EventBus Default = new EventBus();
            //存储EventData和EventHandle的映射关系(没有存放handler的实例而是存放metaData,然后通过反射调用)
            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 eventType, Type handlerType)
            {
                if (mapDic.Keys.Contains(eventType))
                {
                    if (!mapDic[eventType].Contains(handlerType))
                    {
                        mapDic[eventType].Add(handlerType);
                    }
                }
                else
                {
                    mapDic[eventType] = new List<Type>() { handlerType };
                }
            }
    
            public void Unregister<TEventData>(Type handler) where TEventData : IEventData
            {
                var dataType = typeof(TEventData);
                Unregister(dataType, handler);
            }
    
            public void Unregister(Type eventType, Type handlerType)
            {
                if (mapDic.Keys.Contains(eventType))
                {
                    if (mapDic[eventType].Contains(handlerType))
                    {
                        mapDic[eventType].Remove(handlerType);
                    }
                }
            }
    
            public void Trigger<TEventData>(TEventData eventData) where TEventData : IEventData
            {
                var dataType = eventData.GetType();
                //获取当前的EventData绑定的所有Handler
                var handlerTypes = mapDic[dataType];
                foreach (var handlerType in handlerTypes)
                {
                    var methodInfo = handlerType.GetMethod("EventHandle");
                    if (methodInfo != null)
                    {
                        // var handler = Assembly.GetExecutingAssembly().CreateInstance(handlerType.FullName);
                        var handler = Activator.CreateInstance(handlerType);
                        //执行所有的Handler方法
                        methodInfo.Invoke(handler, new object[] { eventData });
                    }
                }
            }
        }

    提供了EventData和Handler的绑定    也可以移除指定的Handler   

    通过调用.Trigger()    然后当前的EventData类型在字典中找到当前类型的所有Handler   执行所有Handler的处理方法

    事件总线通过 EventBusInstaller 来注册 EventBus 和监听事件。 每当IocContainer注册一个类型后 会判断当前类型是否实现IEventHandler   获取具体的EventData类型在EventBus上进行注册

            private void Kernel_ComponentRegistered(string key, IHandler handler)
            {
                /* This code checks if registering component implements any IEventHandler<TEventData> interface, if yes,
                 * gets all event handler interfaces and registers type to Event Bus for each handling event.
                 */
                if (!typeof(IEventHandler).GetTypeInfo().IsAssignableFrom(handler.ComponentModel.Implementation))
                {
                    return;
                }
    
                var interfaces = handler.ComponentModel.Implementation.GetTypeInfo().GetInterfaces();
                foreach (var @interface in interfaces)
                {
                    if (!typeof(IEventHandler).GetTypeInfo().IsAssignableFrom(@interface))
                    {
                        continue;
                    }
    
                    var genericArgs = @interface.GetGenericArguments();
                    if (genericArgs.Length == 1)
                    {
                        _eventBus.Register(genericArgs[0], new IocHandlerFactory(_iocResolver, handler.ComponentModel.Implementation));
                    }
                }
            }

    在ABP中使用EventBus

    1.定义自己的数据对象

        public class MyEventData : EventData
        {
            public string Name { get; set; }
        }

    2.定义自己的处理事件Handler

        public class MyEventHandler : IEventHandler<MyEventData>, ITransientDependency
        {
            public ILogger Logger { set; get; }
            public MyEventHandler()
            {
                Logger = NullLogger.Instance;
            }
            public void HandleEvent(MyEventData eventData)
            {
                Logger.Info($"这是{eventData.Name}自定义的HandEvent处理事件");
            }
        }

    3.通过属性注入 或者构造函数注入 或者直接用静态实例

    public class TaskAppService : ApplicationService
    {
        public IEventBus EventBus { get; set; }
    
        public TaskAppService()
        {
            EventBus = NullEventBus.Instance;
        }
    
        public void CompleteTask(CompleteTaskInput input)
        {
            EventBus.Trigger(new MyEventData {Name= "abc123"});
        }
    }
    EventBus.Default.Trigger(new MyEventData {Name= "abc123"}); 

    https://www.cnblogs.com/myzony/p/9413351.html

  • 相关阅读:
    Codeforces 950E Data Center Maintenance 强连通分量
    Codeforces Round #469 Div. 2 A B C D E
    Codeforces Round #391 A B C D E
    bzoj 4569 [Scoi2016]萌萌哒 并查集 + ST表
    Codeforces 940F Machine Learning 带修改莫队
    How to read the SQL Server Database Transaction Log
    Mysql 主从复制触发器问题
    Git出现 SSL certificate的处理方法
    mac磁盘启动
    发件人地址重写的几种方法记录
  • 原文地址:https://www.cnblogs.com/jiangchengbiao/p/10647663.html
Copyright © 2011-2022 走看看