事件总线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. 引言 事件总线这个概念对你来说可能很陌生,但提到观察者(发布-订阅)模式,你也许就很熟悉.事件总线是对 ...
随机推荐
- 利用腾讯云免费证书打造全https站
什么是https? 超文本传输安全协议(Hypertext Transfer Protocol Secure,缩写为HTTPS)是一种网络安全传输协议http是HTTP协议运行在TCP之上,所有传输的 ...
- C# 中一些类关系的判定方法 C#中关于增强类功能的几种方式 Asp.Net Core 轻松学-多线程之取消令牌
1. IsAssignableFrom实例方法 判断一个类或者接口是否继承自另一个指定的类或者接口. public interface IAnimal { } public interface ID ...
- OAF_OAF组件系列1 - Item Style汇总(概念)
20150506 Created By BaoXinjian
- Linux进程地址空间和虚拟内存
一.虚拟内存 先来看一张图(来自<Linux内核完全剖析>),如下: 分段机制:即分成代码段,数据段,堆栈段.每个内存段都与一个特权级相关联,即0~3,0具有最高特权级(内核),3则是最低 ...
- Python 字典 in 操作符
描述 Python 字典 in 操作符用于判断键(key)是否存在于字典(D)中,如果键在字典中返回True,否则返回False. 在Python2中还可以使用 has_key() 方法,官方文档推荐 ...
- Python tan() 函数
描述 tan() 返回x弧度的正弦值. 语法 以下是 tan() 方法的语法: import math math.tan(x) 注意:tan()是不能直接访问的,需要导入 math 模块,然后通过 m ...
- Javascript变量名混淆细节
前言 UglifyJS会对JS文件的变量名进行混淆处理.要理解Javascript变量混淆的细节.我们须要回答下面几个问题: 1.遇到一个变量myName,我们怎么知道这个myName变量要不要混淆 ...
- python科学计算基础知识
1.导入基本函数库 import numpy as np 2.获取矩阵元素字节数 a=np.array([1,2,3],dtype=np.float32) a.itemsizeoutput: 4 3. ...
- C# xml可序列化多值枚举脚本
代码: using System; using System.Collections.Generic; using System.Xml; using System.Xml.Schema; using ...
- haproxy 配置mysql的代理
应用场境,是如果mysql服务器没有外网的,需要一个有外网的代理服务器做代理,这时就可以用haproxy做个四层的代理: listen mysql bind mode tcp balance roun ...