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. cocos2d-x 颜色

    ccBlendFunc cbl = {GL_SRC_ALPHA, GL_ONE}; Sprite *sprite = Sprite::create("128_00002.png") ...

  2. 浏览器扩展系列————给MSTHML添加内置脚本对象【包括自定义事件】

    原文:浏览器扩展系列----给MSTHML添加内置脚本对象[包括自定义事件] 使用场合: 在程序中使用WebBrowser或相关的控件如:axWebBrowser等.打开本地的html文件时,可以在h ...

  3. C语言中关键字auto、static、register、const、volatile、extern的作用

    原文:C语言中关键字auto.static.register.const.volatile.extern的作用 关键字auto.static.register.const.volatile.exter ...

  4. 事半功倍之StyleCop(一)

    事半功倍之StyleCop(一) 前言 曾几何时,你是否在看别人代码的时候总是在抱怨代码没有注释,命名不规范,代码风格不统一,代码可读性差?是否有一个适合团队开发规范的检查工具? 答案就是大名鼎鼎的S ...

  5. Nagios监控lvs服务

    1在lvs server上安装nrpe客户端: 1.1,rpm方式安装nrpe客户端 下载地址:http://download.csdn.net/detail/mchdba/7493875 [root ...

  6. POJ 3390 Print Words in Lines(DP)

    Print Words in Lines Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 1624 Accepted: 864 D ...

  7. How to:如何在调用外部文件时调试文件路径(常见于使用LaunchAppAndWait和LaunchApp函数)

    原文:How to:如何在调用外部文件时调试文件路径(常见于使用LaunchAppAndWait和LaunchApp函数) IS里调用外部文件的时候,一般都是用LaunchAppAndWait函数,比 ...

  8. 2. SQL Server数据库状态监控 - 错误日志

    原文:2. SQL Server数据库状态监控 - 错误日志 无论是操作系统 (Unix 或者Windows),还是应用程序 (Web 服务,数据库系统等等) ,通常都有自身的日志机制,以便故障时追溯 ...

  9. Visual Studio 2013进行单元测试

    使用Visual Studio 2013进行单元测试--初级篇   1.打开VS2013 --> 新建一个项目.这里我们默认创建一个控制台项目.取名为UnitTestDemo 2.在解决方案里面 ...

  10. C#用WebClient下载File时操作超时的问题

    原文:C#用WebClient下载File时操作超时的问题 今天很SB,被这个问题卡住了.那段代码也是网上找的.结果发现只能下载一个文件,第二次下载的时候就会出现“操作超时”的问题. 这个是原代码: ...