事件总线demo
经过几天的努力拜读大牛高手文章,终于对事件总线有所了解,特此记录下来,以免忘记
1、定义相关的接口:
A 事件接口
public interface IDomainEvent
{
DateTime OccurredOn(); /// <summary>
/// 设置为已读
/// </summary>
/// <returns></returns>
void Read(); /// <summary>
/// 是否已读
/// </summary>
bool IsRead { get; }
}
B 事件订阅接口
public interface IDomainEventSubscriber
{
Type SubscribedToEventType(); void Handle(object domainEvent);
}
2、定义相关实现
A 事件实现
public abstract class DomainEvent : IDomainEvent
{
public readonly DateTime OccurredOnTime;
public string ID; protected DomainEvent()
{
this.ID = Guid.NewGuid().ToString();
this.OccurredOnTime = DateTime.Now;
this.IsRead = false;
} public DateTime OccurredOn()
{
return this.OccurredOnTime;
} public void Read()
{
this.IsRead = true;
} public bool IsRead { get; private set; }
}
B 事件订阅实现
public abstract class DomainEventSubscriber<T> : IDomainEventSubscriber where T : IDomainEvent
{
/// <summary>订阅的事件类型
/// </summary>
/// <returns></returns>
public Type SubscribedToEventType()
{
return typeof(T);
} public abstract void HandleEvent(T domainEvent); public void Handle(object domainEvent)
{
if (domainEvent is T)
{
this.HandleEvent((T)domainEvent);
}
else
{
throw new NotSupportedException(string.Format("当前订阅者支持的事件类型是:{0},当前事件是:{1}", typeof(T).FullName, domainEvent.GetType().FullName));
}
}
}
3、定义事件总线实现
public class DomainEventBus
{
public delegate void DistributeExceptionHandle(IDomainEventSubscriber subscriber, IDomainEvent domainEvent, Exception exception);
/// <summary>
/// Key:DomainEvent的类型,Value订阅该类型事件的订阅者列表
/// </summary>
private static readonly Dictionary<Type, List<IDomainEventSubscriber>> _subscribers = new Dictionary<Type, List<IDomainEventSubscriber>>(); private static readonly object _lockObj = new object(); public event DistributeExceptionHandle DistributeExceptionEvent; private static DomainEventBus _instance;
public static DomainEventBus Instance()
{
if (_instance != null)
return _instance;
var temp = new DomainEventBus();
Interlocked.CompareExchange(ref _instance, temp, null);
return temp;
} public void Publish<T>(T aDomainEvent) where T : IDomainEvent
{
if (aDomainEvent.IsRead)
return; var registeredSubscribers = _subscribers;
if (registeredSubscribers != null)
{
var domainEventType = aDomainEvent.GetType();
List<IDomainEventSubscriber> subscribers;
if (!registeredSubscribers.TryGetValue(domainEventType, out subscribers))
{
aDomainEvent.Read(); //未找到订阅者,但是消息还是消费掉。
return;
} foreach (var domainEventSubscriber in subscribers)
{
var subscribedTo = domainEventSubscriber.SubscribedToEventType();
if (subscribedTo == domainEventType || subscribedTo is IDomainEvent)
{
Distribute(domainEventSubscriber, aDomainEvent);
}
} aDomainEvent.Read();
}
} private void Distribute(IDomainEventSubscriber subscriber, IDomainEvent domainEvent)
{
try
{
subscriber.Handle(domainEvent);
}
catch (Exception ex)
{
OnDistributeExceptionEvent(subscriber, domainEvent, ex);
}
} public void Subscribe(IDomainEventSubscriber aSubscriber)
{
lock (_lockObj)
{
var registeredSubscribers = _subscribers; var domainEventType = aSubscriber.SubscribedToEventType();
List<IDomainEventSubscriber> subscribers; if (!registeredSubscribers.TryGetValue(domainEventType, out subscribers))
{
subscribers = new List<IDomainEventSubscriber>();
registeredSubscribers.Add(domainEventType, subscribers);
} if (subscribers.Any(ent => ent.SubscribedToEventType().FullName == aSubscriber.SubscribedToEventType().FullName && ent.GetType().FullName == aSubscriber.GetType().FullName)) //相同的订阅只接收一次。
return; subscribers.Add(aSubscriber);
}
} protected virtual void OnDistributeExceptionEvent(IDomainEventSubscriber subscriber, IDomainEvent domainEvent, Exception exception)
{
var handler = DistributeExceptionEvent;
if (handler != null)
handler(subscriber, domainEvent, exception);
}
}
4、定义具体的事件
public class OrderCreated : DomainEventCore.DomainEvent
{
public string OrderId { get; private set; } public string UserId { get; private set; } public string Receiver { get; private set; } public OrderCreated(string orderId, string userId, string receiver)
{
this.OrderId = orderId;
this.UserId = userId;
this.Receiver = receiver;
}
}
5、定义具体事件触发后要执行的方法
public class OrderCreatedSubscriberPaymentContext : DomainEventSubscriber<OrderCreated>
{
public override void HandleEvent(OrderCreated domainEvent)
{
//TODO anything
Console.WriteLine("Order ID:{0},i have payment",domainEvent.OrderId);
}
}
public class OrderCreatedSubscriberSellingPriceContext : DomainEventSubscriber<OrderCreated>
{
public override void HandleEvent(OrderCreated domainEvent)
{
//TODO anything
Console.WriteLine("Order ID:{0},i have show price", domainEvent.OrderId);
}
}
6、代码测试
class Program
{
static void Main(string[] args)
{
//事件订阅
DomainEventBus.Instance().Subscribe(new OrderCreatedSubscriberSellingPriceContext());
DomainEventBus.Instance().Subscribe(new OrderCreatedSubscriberPaymentContext()); var tempGuid = Guid.NewGuid().ToString();
var entity = new OrderCreated(tempGuid, "mikechang", "sprite");
Console.WriteLine("生产一个新的订单:{0}",tempGuid);
//事件发布
DomainEventBus.Instance().Publish(entity);
Console.ReadLine();
}
}
事件总线demo的更多相关文章
- android开源项目之OTTO事件总线(二)官方demo解说
官方demo见 https://github.com/square/otto 注意自己该编译版本为2.3以上,默认的1.6不支持match_parent属性,导致布局文件出错. 另外需要手动添加an ...
- DDD~领域事件与事件总线
回到目录 谈谈它 终于有些眉目了,搜刮了很多牛人的资料,英文的,中文的,民国文的,终于小有成就了,同时也做了个DEMO,领域事件这东西好,但需要你明白它之后才会说好,而对于明白领域事件这件事来说,它的 ...
- 事件总线帧---Otto
我们如果这样一种业务场景.如今在做一款及时聊天应用,我们在聊天页面进行收发信息.同一时候也要实时更新前一页面的聊天记录,这时我们该怎样去实现?说说我曾经的实现策略.我使用的是广播接收器BroadCas ...
- 【第一篇】学习 android 事件总线androidEventbus之sticky事件的传递
最近再看eventbus相关代码,首先从使用开始,后期再从源码角度分析eventbus.使用Demo后期公布到github上去. 使用的框架地址:https://github.com/bboyfeiy ...
- 事件总线(Event Bus)知多少
源码路径:Github-EventBus 简书同步链接 1. 引言 事件总线这个概念对你来说可能很陌生,但提到观察者(发布-订阅)模式,你也许就很熟悉.事件总线是对发布-订阅模式的一种实现.它是一种集 ...
- Android事件总线分发库EventBus3.0的简单讲解与实践
Android事件总线分发库EventBus的简单讲解与实践 导语,EventBus大家应该不陌生,EventBus是一款针对Android优化的发布/订阅事件总线.主要功能是替代Intent,Han ...
- Autofac解耦事件总线
事件总线之Autofac解耦 事件总线是通过一个中间服务,剥离了常规事件的发布与订阅(消费)强依赖关系的一种技术实现.事件总线的基础知识可参考圣杰的博客[事件总线知多少] 本片博客不再详细概述事件总线 ...
- C# 事件总线 EventBus
1. 引言 事件总线这个概念对你来说可能很陌生,但提到观察者(发布-订阅)模式,你也许就很熟悉.事件总线是对发布-订阅模式的一种实现.它是一种集中式事件处理机制,允许不同的组件之间进行彼此通信而又不需 ...
- 事件总线(Event Bus)
事件总线(Event Bus)知多少 源码路径:Github-EventBus简书同步链接 1. 引言 事件总线这个概念对你来说可能很陌生,但提到观察者(发布-订阅)模式,你也许就很熟悉.事件总线是对 ...
随机推荐
- ant-jmeter批量脚本
<?xml version="1.0"?> <project name="autotest" default="all" ...
- .NET中那些所谓的新语法
.NET中那些所谓的新语法之四:标准查询运算符与LINQ 摘要: 开篇:在上一篇中,我们了解了预定义委托与Lambda表达式等所谓的新语法,这一篇我们继续征程,看看标准查询运算符和LINQ.标准查询运 ...
- 安装R语言的包的方法
安装R语言的包的方法: 1. 在线安装 在R的控制台,输入类似install.packages("TSA") # 安装 TSA install.packages("TS ...
- 开源 java CMS - FreeCMS2.2 单位管理
项目地址:http://www.freeteam.cn/ 单位管理 FreeCMS支持多单位同一时候使用,并支持无限树级管理. 1. 加入根单位 从左側管理菜单点击单位管理进入. 点击"加入 ...
- STL应用之set
之前在解决一道算法题的时候,应用到set,特意对这个stl的容器类做了一些了解.在我的印象中,set就是一个元素不重复的集合,而事实上也正是这样的.无论从MSDN还是任何其它地方,都会告诉我们set的 ...
- oracle字符串处理函数--待整理
http://www.cnblogs.com/xd502djj/archive/2010/08/11/1797577.html http://blog.csdn.net/qq373591361/art ...
- mysql-cluster 环境安装&配置
一.mysql-cluster 的介绍: 1.说心里话mysql-cluster这货性能上是不行的,之前一个同事测试了来的结果是8个主机组成的mysql-cluster性能 上搞不过一个单机的mysq ...
- NodeJS写日志_Log4js使用详解
今天和大家分享一下NodeJS中写日志的一个常用第三方包:Log4js. 跟随主流Blog特色,先简单介绍下Log4js的基本信息.介绍Log4js之前,需要先说一下Log4***,Log4***是由 ...
- 为什么easyui的datagrid里getSelections还有getChecked只能获取一行值呢?
http://jquery-easyui.wikidot.com/forum/t-280470 如果没有 idField属性,getSelections就只能获取一个行的值了 注意:如果用了前面说的& ...
- bash脚本输入密码不回显问题的解决方法
编写一个bash脚本时,需要用户输入一个密码,方可继续后续流程,但是又要保证用户输入的密码不会被别人看到,因此排除了通过参数将密码传入脚本的方案 不绕圈子,揭晓答案:设置终端状态为“字符不回显”(如果 ...