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