事件总线就是订阅/发布模式的一种实现 事件总线就是为了降低耦合
1.比如在winform中 到处都是事件

触发事件的对象 sender
事件的数据 e
事件的处理逻辑 方法体
通过EventBus实现事件对象和处理逻辑的解耦

1.抽离事件对象 发生时间的事件 触发事件的对象源(可选)
1// 2 // 摘要: 3 // Defines interface for all Event data classes. 4 public interface IEventData 5 { 6 // 7 // 摘要: 8 // The time when the event occured. 9 DateTime EventTime { get; set; } 10 // 11 // 摘要: 12 // The object which triggers the event (optional). 13 object EventSource { get; set; }
2.抽离事件的处理对象
1public interface IEventHandler 2 { 3 } 4 public interface IEventHandler<in TEventData> : IEventHandler 5 { 6 /// <summary> 7 /// Handler handles the event by implementing this method. 8 /// </summary> 9 /// <param name="eventData">Event data</param> 10 void HandleEvent(TEventData eventData); 11 }
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
1public class EventBus : IEventBus 2 { 3 public EventBus() 4 { 5 mapDic = new ConcurrentDictionary<Type, List<Type>>(); 6 } 7 //EventBus单例模式 8 public static EventBus Default = new EventBus(); 9 //存储EventData和EventHandle的映射关系(没有存放handler的实例而是存放metaData,然后通过反射调用) 10 private ConcurrentDictionary<Type, List<Type>> mapDic; 11 12 public void Register<TEventData>(Type handlerType) where TEventData : IEventData 13 { 14 //将数据存储到mapDic 15 var dataType = typeof(TEventData); 16 Register(dataType, handlerType); 17 } 18 19 public void Register(Type eventType, Type handlerType) 20 { 21 if (mapDic.Keys.Contains(eventType)) 22 { 23 if (!mapDic[eventType].Contains(handlerType)) 24 { 25 mapDic[eventType].Add(handlerType); 26 } 27 } 28 else 29 { 30 mapDic[eventType] = new List<Type>() { handlerType }; 31 } 32 } 33 34 public void Unregister<TEventData>(Type handler) where TEventData : IEventData 35 { 36 var dataType = typeof(TEventData); 37 Unregister(dataType, handler); 38 } 39 40 public void Unregister(Type eventType, Type handlerType) 41 { 42 if (mapDic.Keys.Contains(eventType)) 43 { 44 if (mapDic[eventType].Contains(handlerType)) 45 { 46 mapDic[eventType].Remove(handlerType); 47 } 48 } 49 } 50 51 public void Trigger<TEventData>(TEventData eventData) where TEventData : IEventData 52 { 53 var dataType = eventData.GetType(); 54 //获取当前的EventData绑定的所有Handler 55 var handlerTypes = mapDic[dataType]; 56 foreach (var handlerType in handlerTypes) 57 { 58 var methodInfo = handlerType.GetMethod("EventHandle"); 59 if (methodInfo != null) 60 { 61 // var handler = Assembly.GetExecutingAssembly().CreateInstance(handlerType.FullName); 62 var handler = Activator.CreateInstance(handlerType); 63 //执行所有的Handler方法 64 methodInfo.Invoke(handler, new object[] { eventData }); 65 } 66 } 67 } 68 }
提供了EventData和Handler的绑定 也可以移除指定的Handler
通过调用.Trigger() 然后当前的EventData类型在字典中找到当前类型的所有Handler 执行所有Handler的处理方法
事件总线通过 EventBusInstaller 来注册 EventBus 和监听事件。 每当IocContainer注册一个类型后 会判断当前类型是否实现IEventHandler 获取具体的EventData类型在EventBus上进行注册
1private void Kernel_ComponentRegistered(string key, IHandler handler) 2 { 3 /* This code checks if registering component implements any IEventHandler<TEventData> interface, if yes, 4 * gets all event handler interfaces and registers type to Event Bus for each handling event. 5 */ 6 if (!typeof(IEventHandler).GetTypeInfo().IsAssignableFrom(handler.ComponentModel.Implementation)) 7 { 8 return; 9 } 10 11 var interfaces = handler.ComponentModel.Implementation.GetTypeInfo().GetInterfaces(); 12 foreach (var @interface in interfaces) 13 { 14 if (!typeof(IEventHandler).GetTypeInfo().IsAssignableFrom(@interface)) 15 { 16 continue; 17 } 18 19 var genericArgs = @interface.GetGenericArguments(); 20 if (genericArgs.Length == 1) 21 { 22 _eventBus.Register(genericArgs[0], new IocHandlerFactory(_iocResolver, handler.ComponentModel.Implementation)); 23 } 24 } 25 }
在ABP中使用EventBus
1.定义自己的数据对象
1public class MyEventData : EventData 2 { 3 public string Name { get; set; } 4 }
2.定义自己的处理事件Handler
1public class MyEventHandler : IEventHandler<MyEventData>, ITransientDependency 2 { 3 public ILogger Logger { set; get; } 4 public MyEventHandler() 5 { 6 Logger = NullLogger.Instance; 7 } 8 public void HandleEvent(MyEventData eventData) 9 { 10 Logger.Info($"这是{eventData.Name}自定义的HandEvent处理事件"); 11 } 12 }
3.通过属性注入 或者构造函数注入 或者直接用静态实例
1public class TaskAppService : ApplicationService 2{ 3 public IEventBus EventBus { get; set; } 4 5 public TaskAppService() 6 { 7 EventBus = NullEventBus.Instance; 8 } 9 10 public void CompleteTask(CompleteTaskInput input) 11 { 12 EventBus.Trigger(new MyEventData {Name= "abc123"}); 13 } 14} 15 16EventBus.Default.Trigger(new MyEventData {Name= "abc123"});