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

posted @ 2019-04-03 11:19  几清  阅读(2004)  评论(1编辑  收藏  举报