回到目录

谈谈它

终于有些眉目了,搜刮了很多牛人的资料,英文的,中文的,民国文的,终于小有成就了,同时也做了个DEMO,领域事件这东西好,但需要你明白它之后才会说好,而对于明白领域事件这件事来说,它的门槛有点高,居然花了我三天的时间才把它搞定,嗨!

占占给它的定义

领域事件:Domain Event,是针对某个业务来说的,或者说针对某个聚合的业务来说的,例如订单生成这种业务,它可以同时对应一种事件,比如叫做OrderGeneratorEvent,而你的零散业务可能随时会变,加一些业务,减一些业务,而对于订单生成这个事件来说,它是唯一不变的,而我们需要把这些由产生订单而发生变化的事情拿出来,而拿出来的这些业务就叫做"领域事件".其中的领域指的就是订单生成这个聚合;而事件指的就是那些零散业务的统称.

它的主要几个抽象

在面向对象的编程世界里,做这种事情我们需要几个抽象:

领域对象事件标示:(标示接口,接口的一种,用来约束一批对象)IEvent

领域对象的处理方法,行为:(需要让那些零散的模块重写的方法,起个听起来熟悉的名字,叫它handle吧)IEventHandler=>Handle

事件总线:事件处理核心类,承载了事件的发布,订阅与取消订阅的逻辑,EventBus

某个领域对象:为了实现某个业务,而创建的实体类,它里面有事件所需要的数据,它继承了IEvent

某个领域对象的事件:它是一个事件处理类,它实现了IEventHandler,它所处理的事情需要在Handle里去完成

我的Demo的实现

一 结果图:

aaarticlea/png;base64,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" alt="" />

二 核心类:

IEvent接口,标示接口往往都是空的,呵呵

    /// <summary>
/// 事件实体基类
/// </summary>
public interface IEvent
{
}

IEventHandler接口,只有一个行为方法Handle

    /// <summary>
/// 事件处理接口
/// </summary>
/// <typeparam name="TEvent">继承IEvent对象的事件源对象</typeparam>
public interface IEventHandler<TEvent>
where TEvent : IEvent
{
/// <summary>
/// 处理程序
/// </summary>
/// <param name="evt"></param>
void Handle(TEvent evt); }

EventBus是实现事件的核心,在这版里,它支持异步事件机制,使用Task实现,所以它需要运行在.net4.5平台之上

   /// <summary>
/// 事件总线
/// 发布与订阅处理逻辑
/// 核心功能代码
/// </summary>
public class EventBus
{
private EventBus() { } private static EventBus _eventBus = null;
private readonly object sync = new object();
/// <summary>
/// 对于事件数据的存储,目前采用内存字典
/// </summary>
private static Dictionary<Type, List<object>> eventHandlers = new Dictionary<Type, List<object>>();
/// <summary>
// checks if the two event handlers are equal. if the event handler is an action-delegated, just simply
// compare the two with the object.Equals override (since it was overriden by comparing the two delegates. Otherwise,
// the type of the event handler will be used because we don't need to register the same type of the event handler
// more than once for each specific event.
/// </summary>
private readonly Func<object, object, bool> eventHandlerEquals = (o1, o2) =>
{
var o1Type = o1.GetType();
var o2Type = o2.GetType();
if (o1Type.IsGenericType &&
o1Type.GetGenericTypeDefinition() == typeof(ActionDelegatedEventHandler<>) &&
o2Type.IsGenericType &&
o2Type.GetGenericTypeDefinition() == typeof(ActionDelegatedEventHandler<>))
return o1.Equals(o2);
return o1Type == o2Type;
};
/// <summary>
/// 初始化空的事件总件
/// </summary>
public static EventBus Instance
{
get
{
return _eventBus ?? (_eventBus = new EventBus());
}
}
/// <summary>
/// 通过XML文件初始化事件总线,订阅信自在XML里配置
/// </summary>
/// <returns></returns>
public static EventBus InstanceForXml()
{
if (_eventBus == null)
{
XElement root = XElement.Load(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "EventBus.xml"));
foreach (var evt in root.Elements("Event"))
{
List<object> handlers = new List<object>(); Type publishEventType = Type.GetType(evt.Element("PublishEvent").Value);
foreach (var subscritedEvt in evt.Elements("SubscribedEvents"))
foreach (var concreteEvt in subscritedEvt.Elements("SubscribedEvent"))
handlers.Add(Type.GetType(concreteEvt.Value)); eventHandlers[publishEventType] = handlers;
} _eventBus = new EventBus();
}
return _eventBus;
} #region 事件订阅&取消订阅,可以扩展
/// <summary>
/// 订阅事件列表
/// </summary>
/// <param name="type"></param>
/// <param name="subTypeList"></param>
public void Subscribe<TEvent>(IEventHandler<TEvent> eventHandler)
where TEvent : class, IEvent
{
lock (sync)
{
var eventType = typeof(TEvent);
if (eventHandlers.ContainsKey(eventType))
{
var handlers = eventHandlers[eventType];
if (handlers != null)
{
if (!handlers.Exists(deh => eventHandlerEquals(deh, eventHandler)))
handlers.Add(eventHandler);
}
else
{
handlers = new List<object>();
handlers.Add(eventHandler);
}
}
else
eventHandlers.Add(eventType, new List<object> { eventHandler });
}
}
/// <summary>
/// 订阅事件实体
/// </summary>
/// <param name="type"></param>
/// <param name="subTypeList"></param>
public void Subscribe<TEvent>(Action<TEvent> eventHandlerFunc)
where TEvent : class, IEvent
{
Subscribe<TEvent>(new ActionDelegatedEventHandler<TEvent>(eventHandlerFunc));
}
public void Subscribe<TEvent>(IEnumerable<IEventHandler<TEvent>> eventHandlers)
where TEvent : class, IEvent
{
foreach (var eventHandler in eventHandlers)
Subscribe<TEvent>(eventHandler);
}
/// <summary>
/// 取消订阅事件
/// </summary>
/// <param name="type"></param>
/// <param name="subType"></param>
public void Unsubscribe<TEvent>(IEventHandler<TEvent> eventHandler)
where TEvent : class, IEvent
{
lock (sync)
{
var eventType = typeof(TEvent);
if (eventHandlers.ContainsKey(eventType))
{
var handlers = eventHandlers[eventType];
if (handlers != null
&& handlers.Exists(deh => eventHandlerEquals(deh, eventHandler)))
{
var handlerToRemove = handlers.First(deh => eventHandlerEquals(deh, eventHandler));
handlers.Remove(handlerToRemove);
}
}
}
}
public void Unsubscribe<TEvent>(IEnumerable<IEventHandler<TEvent>> eventHandlers)
where TEvent : class, IEvent
{
foreach (var eventHandler in eventHandlers)
Unsubscribe<TEvent>(eventHandler);
}
public void Unsubscribe<TEvent>(Action<TEvent> eventHandlerFunc)
where TEvent : class, IEvent
{
Unsubscribe<TEvent>(new ActionDelegatedEventHandler<TEvent>(eventHandlerFunc));
}
#endregion #region 事件发布
/// <summary>
/// 发布事件,支持异步事件
/// </summary>
/// <typeparam name="TEvent"></typeparam>
/// <param name="evnt"></param>
public void Publish<TEvent>(TEvent evnt)
where TEvent : class, IEvent
{
if (evnt == null)
throw new ArgumentNullException("evnt");
var eventType = evnt.GetType();
if (eventHandlers.ContainsKey(eventType)
&& eventHandlers[eventType] != null
&& eventHandlers[eventType].Count > )
{
var handlers = eventHandlers[eventType];
foreach (var handler in handlers)
{
var eventHandler = handler as IEventHandler<TEvent>;
if (eventHandler.GetType().IsDefined(typeof(HandlesAsynchronouslyAttribute), false))
{
Task.Factory.StartNew((o) => eventHandler.Handle((TEvent)o), evnt);
}
else
{
eventHandler.Handle(evnt);
}
}
}
} public void Publish<TEvent>(TEvent evnt, Action<TEvent, bool, Exception> callback, TimeSpan? timeout = null)
where TEvent : class, IEvent
{
if (evnt == null)
throw new ArgumentNullException("evnt");
var eventType = evnt.GetType();
if (eventHandlers.ContainsKey(eventType) &&
eventHandlers[eventType] != null &&
eventHandlers[eventType].Count > )
{
var handlers = eventHandlers[eventType];
List<Task> tasks = new List<Task>();
try
{
foreach (var handler in handlers)
{
var eventHandler = handler as IEventHandler<TEvent>;
if (eventHandler.GetType().IsDefined(typeof(HandlesAsynchronouslyAttribute), false))
{
tasks.Add(Task.Factory.StartNew((o) => eventHandler.Handle((TEvent)o), evnt));
}
else
{
eventHandler.Handle(evnt);
}
}
if (tasks.Count > )
{
if (timeout == null)
Task.WaitAll(tasks.ToArray());
else
Task.WaitAll(tasks.ToArray(), timeout.Value);
}
callback(evnt, true, null);
}
catch (Exception ex)
{
callback(evnt, false, ex);
}
}
else
callback(evnt, false, null);
} #endregion }

一个具体的领域对象,它继承IEvent

    /// <summary>
/// 添加订单的事件
/// </summary>
public class OrderGeneratorEvent : IEvent
{
public int OrderID { get; set; }
}

一个为OrderGeneratorEvent工作的领域事件,它用来为客户发邮件

   /// <summary>
/// 发邮件功能
/// </summary>
public class OrderAddedEventHandler_SendEmail : IEventHandler<OrderGeneratorEvent>
{
public void Handle(OrderGeneratorEvent evt)
{
Console.WriteLine("Order_Number:{0},Send a Email.", evt.OrderID);
}
}

下面看一个主程序:

   static void Main(string[] args)
{
    EventBus.Instance.Subscribe(new OrderAddedEventHandler_SendEmail());
            var entity = new OrderGeneratorEvent { OrderID = 1 };
            Console.WriteLine("生成一个订单,单号为{0}", entity.OrderID);
            EventBus.Instance.Publish(entity);
            Console.ReadKey();
}

下面是运行结果:

aaarticlea/png;base64,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" alt="" />

嗨,终于理解这东西了,呵呵,在此感谢一下晴阳兄,它对DDD的贡献非常大...

回到目录

DDD~领域事件与事件总线的更多相关文章

  1. DDD~领域事件中使用分布式事务

    回到目录 对于一个聚合来说,它可能会被附加很多事件,这里我们叫它领域事务,因为一个聚会我们可以把它理解成一个领域,一个业务.对于领域事件不清楚的同学可以看看我的这篇文章<DDD~领域事件与事件总 ...

  2. DDD领域事件与事件总线源码下载

    最近在看领域事件的文章.看到了“张占岭”的<DDD~领域事件与事件总线> 原文地址:http://www.cnblogs.com/lori/p/3476703.html 遗憾的是没有提供下 ...

  3. DDD领域驱动设计:领域事件

    1 前置阅读 在阅读本文章之前,你可以先阅读: DDD领域驱动设计是什么 DDD领域驱动设计:实体.值对象.聚合根 DDD领域驱动设计:仓储 MediatR一个优秀的.NET中介者框架 2 什么是领域 ...

  4. DDD领域驱动之干活(四)补充篇!

    距离上一篇DDD系列完结已经过了很长一段时间,项目也搁置了一段时间,想想还是继续完善下去. DDD领域驱动之干货(三)完结篇! 上一篇说到了如何实现uow配合Repository在autofac和au ...

  5. DDD领域驱动之干货(四)补充篇!

    距离上一篇DDD系列完结已经过了很长一段时间,项目也搁置了一段时间,想想还是继续完善下去. DDD领域驱动之干货(三)完结篇! 上一篇说到了如何实现uow配合Repository在autofac和au ...

  6. 基于事件驱动的DDD领域驱动设计框架分享(附源代码)

    原文:基于事件驱动的DDD领域驱动设计框架分享(附源代码) 补充:现在再回过头来看这篇文章,感觉当初自己偏激了,呵呵.不过没有以前的我,怎么会有现在的我和现在的enode框架呢?发现自己进步了真好! ...

  7. 关于DDD领域驱动设计的理论知识收集汇总

    原文:关于DDD领域驱动设计的理论知识收集汇总 最近一直在学习领域驱动设计(DDD)的理论知识,从网上搜集了一些个人认为比较有价值的东西,贴出来和大家分享一下: 我一直觉得不要盲目相信权威,比如不能一 ...

  8. 浅谈我对DDD领域驱动设计的理解

    从遇到问题开始 当人们要做一个软件系统时,一般总是因为遇到了什么问题,然后希望通过一个软件系统来解决. 比如,我是一家企业,然后我觉得我现在线下销售自己的产品还不够,我希望能够在线上也能销售自己的产品 ...

  9. DDD 领域驱动设计-商品建模之路

    最近在做电商业务中,有关商品业务改版的一些东西,后端的架构设计采用现在很流行的微服务,有关微服务的简单概念: 微服务是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成.系统中的各个微服务可被独 ...

随机推荐

  1. POST 500 Internal Server Error

    今天调试公司web后台时发现一个POST 500 Internal Server Error的错误. 本来VS本地调试没有发现这个问题,然后发布到服务器时才出现了.然后找了好久没找到什么原因,再仔细在 ...

  2. jsp页面输入小写金额转大写

    <script> function chineseNumber(num){ if (isNaN(num) || num > Math.pow(10, 12)) return &quo ...

  3. terminal崩溃打不开的一种原因以及ubuntu下matlab权限不够的解决办法

    为了解决点击matlab图标闪退的问题,我往.bashrc添加了如下命令: source /usr/local/MATLAB/R2015b/bin/matlab 结果导致打开新的terminal闪退. ...

  4. 通过挂载系统光盘搭建本地yum仓库

    1,配置本地yum源: 把系统光盘挂载到文件夹aaa(aaa为自己创建的文件夹). [root@localhost /]# mount dev/cdrom /aaa 2,修改yum配置文件: yum的 ...

  5. 【洛谷P3076】Taxi

    这道题值得好好想一会 我们通过对一些小数据的手算,以及对于每段路程的拆分,可以发现: 1.每个st对应的ed这段路程无论如何都要算上 2.额外还要计算的一段路程,就是"切换"费用 ...

  6. svn不能添加.a文件的解决方法

    上次说用svn add命令添加.a文件,下面是另外的一种解决办法: 修改~/.subversion/config文件,增加一条 # global-ignores = *.o *.lo *.la *.a ...

  7. Python排列组合问题

    1.字符串的全排列 问题描述:打印出原字符串中所有字符的所有排列.——将输入字符串中的每个字符作为一个不同的字符看待,即使它们是重复的,如'aaa'应打印6次. Python可以用生成器解决: def ...

  8. vs.net2008工具栏上找不到debug/release选项

    使用vs.net多年,以前不时会用到release发布,近几年几乎不用的.近来生成时感觉有些项目使用了release选项,因为生成的dll的位置变了.于是想调整回bebug,发现vs.net2008的 ...

  9. java中打印变量地址

    在java中打印变量的地址 这个代码是在startoverflow上看到的,跟大家分享一下. import sun.misc.Unsafe; import java.lang.reflect.Fiel ...

  10. 2016-11-15mysql优化笔记

    1.mysql连接数:MYSQL数据库安装完成后,默认最大连接数是100,一般流量稍微大一点的论坛或网站这个连接数是远远不够的,连接数少的话,在大并发下连接数会不够用,会有很多线程在等待其他连接释放, ...