在C#中,我们可以在一个类中界说本身的事件,而其他的类可以订阅该事件,当某些工作产生时,可以通知到该类。这对付桌面应用或者独立的windows处事来说长短常有用的。但对付一个web应用来说是有点问题的,因为东西都是在web请求中创建的,而且这些东西生命周期都很短,因而注册某些类的事件是很困难的。别的,注册其他类的事件会使得类紧耦合。事件总线便可以用来解耦并反复操作应用中的逻辑。
事件总线带来的好处和引入的问题好处对照明显,就是独立出一个颁布订阅模块,挪用者可以通过使用这个模块,屏蔽一些线程切换问题,简单地实现颁布订阅成果。
坏处可能对照隐晦,但这些需要足够引起我们的重视
大量的滥用,将导致逻辑的分手,呈现问题后很难定位。
没步伐实现强类型,在编译的时候就发明问题。
代码可读性有些问题,IDE无法识别这些协议,对IDE不友好。
总得来说,如果项目里面有大量的事件交互,那么还是可以通过EventBus来实现,否则还是保举本身在模块内部实现不雅察看者模式。
示例代码
所以今天介绍一个简单的事件总线,它是事件颁布订阅模式的实现,让我们能在范围驱动设计(DDD)中以事件的弱引用素质对我们的模块和范围界限很好的解耦设计。
目前,所有的源代码已经提交到github 上,地点:https://github.com/weizhong1988/Weiz.EventBus
措施目录布局如下:
事件总线事件总线是被所有触发并措置惩罚惩罚事件的其他类共享的单例东西。要使用事件总线,首先应该获得它的一个引用。下面有两种要领来措置惩罚惩罚:
订阅事件触发事件之前,应该先要界说该事件。EventBus为我们供给了Subscribe 要领来订阅事件:
public void Subscribe<TEvent>(IEventHandler<TEvent> eventHandler) where TEvent : IEvent { //同步锁 lock (_syncObject) { //获取范围模型的类型 var eventType = typeof(TEvent); //如果此范围类型在事件总线中已注册过 if (_dicEventHandler.ContainsKey(eventType)) { var handlers = _dicEventHandler[eventType]; if (handlers != null) { handlers.Add(eventHandler); } else { handlers = new List<object> { eventHandler }; } } else { _dicEventHandler.Add(eventType, new List<object> { eventHandler }); } } }
所以的事件都集成自IEvent,该类包罗了类措置惩罚惩罚事件需要的属性。
var sendEmailHandler = new UserAddedEventHandlerSendEmail(); var sendMessageHandler = new UserAddedEventHandlerSendMessage(); var sendRedbagsHandler = new UserAddedEventHandlerSendRedbags(); Weiz.EventBus.Core.EventBus.Instance.Subscribe(sendEmailHandler); Weiz.EventBus.Core.EventBus.Instance.Subscribe(sendMessageHandler); //Weiz.EventBus.Core.EventBus.Instance.Subscribe<UserGeneratorEvent>(sendRedbagsHandler); Weiz.EventBus.Core.EventBus.Instance.Subscribe<OrderGeneratorEvent>(sendRedbagsHandler);
颁布事件对付事件源,则可以通过Publish 要领颁布事件。触发一个事件很简单,如下所示:
public void Publish<TEvent>(TEvent tEvent, Action<TEvent, bool, Exception> callback) where TEvent : IEvent { var eventType = typeof(TEvent); if (_dicEventHandler.ContainsKey(eventType) && _dicEventHandler[eventType] != null && _dicEventHandler[eventType].Count > 0) { var handlers = _dicEventHandler[eventType]; try { foreach (var handler in handlers) { var eventHandler = handler as IEventHandler<TEvent>; eventHandler.Handle(tEvent); callback(tEvent, true, null); } } catch (Exception ex) { callback(tEvent, false, ex); } } else { callback(tEvent, false, null); } }
下面是颁布事件的挪用: