EventBus事件总线
EventBus事件总线的使用-自己实现事件总线
在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);
}
}

下面是发布事件的调用:
var orderGeneratorEvent = new OrderGeneratorEvent { OrderId = Guid.NewGuid() }; System.Console.WriteLine("{0}下单成功", orderGeneratorEvent.OrderId); Weiz.EventBus.Core.EventBus.Instance.Publish(orderGeneratorEvent, CallBack);
定义处理事件
要处理一个事件,应该要实现IEventHandler接口,如下所示:

/// <summary>
/// send email
/// </summary>
public class UserAddedEventHandlerSendEmail : IEventHandler<UserGeneratorEvent>
{ public void Handle(UserGeneratorEvent tEvent)
{
System.Console.WriteLine(string.Format("{0}的邮件已发送", tEvent.UserId));
}
}

处理多事件
在一个单一的处理句柄中,可以处理多个事件。这时,你应该为每个事件实现IEventHandler。比如:

/// <summary>
/// red bags.
/// </summary>
public class UserAddedEventHandlerSendRedbags : IEventHandler<UserGeneratorEvent>,IEventHandler<OrderGeneratorEvent>
{
public void Handle(OrderGeneratorEvent tEvent)
{
System.Console.WriteLine(string.Format("{0}的下单红包已发送", tEvent.OrderId));
} public void Handle(UserGeneratorEvent tEvent)
{
System.Console.WriteLine(string.Format("{0}的注册红包已发送", tEvent.UserId));
}
}

最后
以上,就把事件总线介绍完了,完整的代码,请到github 上下载,这个只是EventBus 的简单实现,各位可以根据自己的实际场景和需求,优化修改。
作者:章为忠
出处:http://www.fpeach.com/
EventBus事件总线的更多相关文章
- Guava - EventBus(事件总线)
Guava在guava-libraries中为我们提供了事件总线EventBus库,它是事件发布订阅模式的实现,让我们能在领域驱动设计(DDD)中以事件的弱引用本质对我们的模块和领域边界很好的解耦设计 ...
- EventBus(事件总线)
EventBus(事件总线) Guava在guava-libraries中为我们提供了事件总线EventBus库,它是事件发布订阅模式的实现,让我们能在领域驱动设计(DDD)中以事件的弱引用本质对我们 ...
- dhroid - eventbus 事件总线
你听过onClick 事件,onItemClick 事件,事件总线不一定听过吧, eventbus 事件总线也是一个编程思想,为什么要设计EventBus了,因为他是领域驱动设计中比不可少的模块,它承 ...
- EventBus 事件总线 案例
简介 地址:https://github.com/greenrobot/EventBus EventBus是一个[发布 / 订阅]的事件总线.简单点说,就是两人[约定]好怎么通信,一人发布消息,另外一 ...
- C#总结(六)EventBus事件总线的使用-自己实现事件总线
在C#中,我们可以在一个类中定义自己的事件,而其他的类可以订阅该事件,当某些事情发生时,可以通知到该类.这对于桌面应用或者独立的windows服务来说是非常有用的.但对于一个web应用来说是有点问题的 ...
- Android 开发 框架系列 EventBus 事件总线
介绍 GitHub:https://github.com/greenrobot/EventBus 先聊聊EventBus 线程总线是干什么的,使用环境,优点.缺点. 干什么的? 一句话,简单统一数据传 ...
- EventBus事件总线(牛x版)
事件总线: public interface IEventBus { void Trigger<TEvent>(TEvent eventData, string topic = null) ...
- EventBus 事件总线之我的理解
用例:假设公司发布了一个公告 需要通过短信 和 邮件分别2种方式 通知员工 1:首先我们建立领域模型 /// <summary> /// 领域核心基类 /// </summary&g ...
- Orchard EventBus 事件总线及 IEventHandler作用
事件总线接口定义: public interface IEventBus : IDependency { IEnumerable Notify(string messageName, IDiction ...
随机推荐
- 【Lua】Lua + openresty遍历文件目录
OpenResty (也称为 ngx_openresty)是一个全功能的 Web 应用服务器,它打包了标准的 Nginx 核心,很多的常用的第三方模块,以及它们的大多数依赖项. 今天用OpenRest ...
- xamarin for android webservice
首先新建一个空网站,添加一个webservice服务.然后在UserWebService.cs类里编写对外服务的方法 [WebMethod] public string IsCorret(string ...
- PHP的parse_ini_file()函数,解释结构类型php.ini格式的文件
1.直接读取,返回一维数组 如: "test.ini" 的内容: [names] me = Robert you = Peter [urls] first = "http ...
- python3根据地址批量获取百度地图经纬度
python3代码如下: import requests import time def get_mercator(addr): url= 'http://api.map.baidu.com/geoc ...
- 【find】Linux中find常见用法示例
1.根据 某个名字在某个目录下进行查找 find /etc/ -name "*.conf" 在/etc/目录下 查找 后缀名为conf 的文件
- A space or line break was encountered after the "@" character. Only valid identifiers, keywords, comments, "(" and "{" are valid at the start of a code block and they must occur immediately following
mvc 控制器调用分布视图出错,("A space or line break was encountered after the "@" character. Only ...
- window.open()被浏览器拦截问题汇总
一.问题描述 最近在做项目的时候碰到了使用window.open被浏览器拦截的情况,虽然在自己的环境可以对页面进行放行,但是对用户来说,不能要求用户都来通过拦截.何况当出现拦截时,很多用户根本不知道发 ...
- Html5本地存储+本地数据库+离线存储
首先介绍什么叫存储: cache:通常把它叫做缓存,功能就是把从DB,或者磁盘拿出来的东西放在缓存里面,这样的话可以减少读取磁盘的IO. 磁盘文件:通常把一些图片或者一些视频都存放在磁盘上. 数据库: ...
- Microsoft Windows Scripting Self-Paced Learning Guide
http://www.mums.ac.ir/shares/hit/eduhit/book/windowsscripting.pdfhttp://support.microsoft.com/kb/926 ...
- after() 和 remove() 实现替换
<div class="replacedDiv">this is the replaced div</div> <script> ...