事件总线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. 引言 事件总线这个概念对你来说可能很陌生,但提到观察者(发布-订阅)模式,你也许就很熟悉.事件总线是对 ...
随机推荐
- python学习笔记011——内置函数dir()
1 描述 dir()函数可以查看(打印)对象的属性和方法.不管时那种对象(python中一切皆对象)类型(数据,模块)都有自己的属性和方法. dir() 函数不带参数时,返回当前范围内的变量.方法和定 ...
- go 学习笔记(4) ---项目结构
go install和go build之争.目前,IDEA插件和LiteIDE都采用了go build.Eclipse插件采用了go install.官方推荐go install方式编译项目,官方项目 ...
- 管道读写规则和Pipe Capacity、PIPE_BUF
一.当没有数据可读时 O_NONBLOCK disable:read调用阻塞,即进程暂停执行,一直等到有数据来到为止. O_NONBLOCK enable:read调用返回-1,errno值为EAGA ...
- sqlserver把小数点后面多余的0去掉
Sql中想把小数点后多余的0去掉,怎么办? select 5000/10000.0 --想变成0.5select 5500/10000.0 --想变成0.55select 5550/10000.0 - ...
- 云从科技 OCR任务 pixel-anchor 方法
云从科技提出了一种端到端的深度学习文本检测框架Pixel-Anchor,通过特征共享的方式高效的把像素级别的图像语义分割和锚检测回归放入一个网络之中, 把像素分割结果转换为锚检测回归过程中的一种注意力 ...
- python map 详解
python中的map函数应用于每一个可迭代的项,返回的是一个结果list.如果有其他的可迭代参数传进来,map函数则会把每一个参数都以相应的处理函数进行迭代处理.map()函数接收两个参数,一个是函 ...
- hdu4901The Romantic Hero
#include<iostream> #include<map> #include<string> #include<cstring> #include ...
- iOS学习笔记(八)——iOS网络通信http之NSURLConnection
转自:http://blog.csdn.net/xyz_lmn/article/details/8968182 移动互联网时代,网络通信已是手机终端必不可少的功能.我们的应用中也必不可少的使用了网络通 ...
- Cocos2d-x stack corruption detected: aborted
adb logcat错误 :堆栈错误,,或者访问过界...通常不太好调试:: 但是以下两种情况最最常见: 1. ]; strcpy(aa,"abcdefghijk123457890" ...
- AC Again hdoj 1582 搜索
AC Again Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...