EventBus实现 - 发布订阅 - XML加载

受到CQRS的影响,写了个EventBus,能实现发布订阅模式执行event,在DDD模型中,可以使用如下代码触发事件:

EventBus bus = EventBus.Instance();
bus.Publish(new OrderAddedEvent());

解决方案结构图如下,很简单易懂:

xml事件配置代码sample如下(1个event可以定义多个订阅者,如下):

<?xml version="1.0" encoding="utf-8" ?>
<Events>
<Event>
<PublishEvent>ConsoleApplication2.code.Events.OrderAddedEvent</PublishEvent>
<SubscribedEvents>
<SubscribedEvent>ConsoleApplication2.code.EventHandlers.OrderAddedEventHandler_CachePrepare</SubscribedEvent>
<SubscribedEvent>ConsoleApplication2.code.EventHandlers.OrderAddedEventHandler_PDFGenerate</SubscribedEvent>
</SubscribedEvents>
</Event>
<Event>
<PublishEvent>ConsoleApplication2.code.Events.OrderDeletedEvent</PublishEvent>
<SubscribedEvents>
<SubscribedEvent>ConsoleApplication2.code.EventHandlers.OrderDeletedEventHandler_NotifyClient</SubscribedEvent>
<SubscribedEvent>ConsoleApplication2.code.EventHandlers.OrderDeletedEventHandler_RemovCache</SubscribedEvent>
</SubscribedEvents>
</Event>
</Events>

我们先来定义Event:

public class BaseEvent         //空的,不需要实现其他方法
{
}
public class OrderAddedEvent : BaseEvent //订单已经加入,触发的event
{
}
public class OrderDeletedEvent : BaseEvent //订单已经删除,触发的event
{
public Guid OrderId { get; set; }
public OrderDeletedEvent(Guid orderId)
{
this.OrderId = orderId;
}
}

定义事件的处理程序:

public interface IEventHandler<T>
where T : BaseEvent
{
void Handle(T evt);
}
public class OrderDeletedEventHandler_NotifyClient : IEventHandler<OrderDeletedEvent>
{
public void Handle(OrderDeletedEvent evt)
{
Console.WriteLine("[Order deleted] Notified.");
}
}

上面2个步骤很简单,只是简单的定义事件、事件处理程序,要怎样才能触发事件处理程序并且做成可配置的方式呢?请看下面代码即可:

private static Dictionary<Type, List<Type>> eventMapping = new Dictionary<Type, List<Type>>();

XElement root=XElement.Load(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "EventBus.xml"));  //这个xml文件需要设置为一直拷贝到程序目录中
foreach (var evt in root.Elements("Event"))
{
List<Type> eventHandlers = new List<Type>(); Type publishEventType = Type.GetType(evt.Element("PublishEvent").Value);
foreach (var subscritedEvt in evt.Elements("SubscribedEvents"))
foreach (var concreteEvt in subscritedEvt.Elements("SubscribedEvent"))
eventHandlers.Add(Type.GetType(concreteEvt.Value)); eventMapping[publishEventType] = eventHandlers; //加入Dictionary中
}

再来上发布代码:

        public void Publish(BaseEvent evt)
{
var result = from tb in eventMapping
where tb.Key.Equals(evt.GetType())
select tb; foreach (KeyValuePair<Type, List<Type>> t in result.ToList())
{
foreach (Type tt in t.Value)
{
Type targetType = tt;
MethodInfo mi=targetType.GetMethod("Handle"); //这个Handle文本字符串,必须和IEventHandler<T>中定义的方法一致
if(mi==null)
continue; object o = Activator.CreateInstance(targetType); //new实例
mi.Invoke(o, new object[] { evt }); //调用方法,并且传入事件参数
}
}
}

运行效果图如下:

代码下载

自省推动进步,视野决定未来。
心怀远大理想。
为了家庭幸福而努力。
用A2D科技,服务社会。
 
分类: 架构可扩展

EventBus实现 - 发布订阅 - XML加载的更多相关文章

  1. 实战android菜单项之XML加载菜单与动态菜单项[转]

    原文地址:http://blog.csdn.net/kaiwii/article/details/7767225 自定义android应用程序的菜单项首先要知道切入点.经过学习,知道主要是两个Acti ...

  2. JAVA Web.xml 加载顺序

    web.xml加载过程(步骤): 1.启动WEB项目的时候,容器(如:Tomcat)会去读它的配置文件web.xml.读两个节点: <listener></listener> ...

  3. Java web.xml加载顺序

     web.xml加载过程(步骤): 1.启动WEB项目的时候,容器(如:Tomcat)会去读它的配置文件web.xml.读两个节点:   <listener></listener&g ...

  4. web.xml加载过程

    web.xml加载过程:1 启动WEB项目的时候,容器(如:Tomcat)会读他的配置文件web.xml读两个节点  <listener></listener>和<con ...

  5. 想要配置文件生效 需要通过添加到web.xml加载到内存中

    想要配置文件生效 需要通过添加到web.xml加载到内存中

  6. 使用EventBus + Redis发布订阅模式提升业务执行性能

    前言 最近一直奔波于面试,面了几家公司的研发.有让我受益颇多的面试经验,也有让我感觉浪费时间的面试经历~因为疫情原因,最近宅在家里也没事,就想着使用Redis配合事件总线去实现下具体的业务. 需求 一 ...

  7. web.xml加载顺序

    一 1.启动一个WEB项目的时候,WEB容器会去读取它的配置文件web.xml,读取<listener>和<context-param>两个结点. 2.紧急着,容创建一个Ser ...

  8. WEB容器启动——web.xml加载详解

    最近在看spring的源码,关于web.xml文件在容器(Tomcat.JBOSS等)启动时加载顺序问题很混乱,通过搜集资料,得出以下的结论: 1.加载顺序与它们在 web.xml 文件中的先后顺序无 ...

  9. maven pom.xml加载不同properties配置[转]

    可以参考http://www.openwebx.org/docs/autoconfig.html 1.pom.xml =========================== <!-- 不同的打包 ...

随机推荐

  1. MySQL 存储过程 经常使用语法

    MySQL 存储过程是从 MySQL 5.0 開始添加的新功能.存储过程的长处有一箩筐.只是最基本的还是运行效率和SQL 代码封装.特别是 SQL 代码封装功能,假设没有存储过程,在外部程序訪问数据库 ...

  2. Pointers to classes (From the note of my firend)

     Pointers to classes Objects can also be pointed to by pointers: Once declared, a class becomes a ...

  3. 使用Row_Number()分页优化

    记一次SQLServer的分页优化兼谈谈使用Row_Number()分页存在的问题   最近有项目反应,在服务器CPU使用较高的时候,我们的事件查询页面非常的慢,查询几条记录竟然要4分钟甚至更长,而且 ...

  4. PhotoShop CC安装抠图插件KnockOut 2

    1.KnockOut 2只有32位版本,因此需要给32位的PhotoShop CC安装. 2.下载地址:http://www.cr173.com/soft/28207.html 3.安装KnockOu ...

  5. 检测浏览器版本类型的JavaScript代码,终极版

    下面的JavaScript代码,不仅可以判断PC端浏览器类型,还可以判断安卓.iOS.其他智能手机.平板电脑或游戏系统. 说废话貌似不是我的风格哈,直接上代码吧: var client = funct ...

  6. 【【分享】深入浅出WPF全系列教程及源码 】

    因为原书作者的一再要求,在此声明,本书中的部分内容引用了原书名为<深入浅出WPF>的部分内容,假设博文不能满足你现有的学习须要,能够购买正版图书! 本人10月份提出离职,可是交接非常慢,预 ...

  7. Asp.Net MVC页面静态化功能实现一:利用IHttpModule和ResultFilter

    由于公司现在所采用的是一套CMS内容管理系统的框架,所以最近项目中有一个需求提到要求实现页面静态化的功能.在网上查询了一些资料和文献,最后采用的是小尾鱼的池塘提供的 利用ResultFilter实现a ...

  8. android 实现分享功能两种方法

    当我想做一个智能的记事本的时候,我就在尝试自己写一组分享功能.后来才知道,原来每个社交软件中都有自己的分享接口. 这就大大减少了我们的代码量了. 第一种方法:特点--简单 package com.ex ...

  9. JAVA开发语言基础

    很多时候我们都不知道,为什么android最开始要用java作为基础语言 看看知乎上都是怎么回答的 为什么java最初成为android开发的基础语言 ------------------------ ...

  10. Linux根目录下文件说明

    /bin:存放最常用命令: /boot:启动Linux的核心文件: /dev:设备文件: /etc:存放各种配置文件: /home:用户主目录: /lib:系统最基本的动态链接共享库: /mnt:一般 ...