经过几天的努力拜读大牛高手文章,终于对事件总线有所了解,特此记录下来,以免忘记

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的更多相关文章

  1. android开源项目之OTTO事件总线(二)官方demo解说

    官方demo见  https://github.com/square/otto 注意自己该编译版本为2.3以上,默认的1.6不支持match_parent属性,导致布局文件出错. 另外需要手动添加an ...

  2. DDD~领域事件与事件总线

    回到目录 谈谈它 终于有些眉目了,搜刮了很多牛人的资料,英文的,中文的,民国文的,终于小有成就了,同时也做了个DEMO,领域事件这东西好,但需要你明白它之后才会说好,而对于明白领域事件这件事来说,它的 ...

  3. 事件总线帧---Otto

    我们如果这样一种业务场景.如今在做一款及时聊天应用,我们在聊天页面进行收发信息.同一时候也要实时更新前一页面的聊天记录,这时我们该怎样去实现?说说我曾经的实现策略.我使用的是广播接收器BroadCas ...

  4. 【第一篇】学习 android 事件总线androidEventbus之sticky事件的传递

    最近再看eventbus相关代码,首先从使用开始,后期再从源码角度分析eventbus.使用Demo后期公布到github上去. 使用的框架地址:https://github.com/bboyfeiy ...

  5. 事件总线(Event Bus)知多少

    源码路径:Github-EventBus 简书同步链接 1. 引言 事件总线这个概念对你来说可能很陌生,但提到观察者(发布-订阅)模式,你也许就很熟悉.事件总线是对发布-订阅模式的一种实现.它是一种集 ...

  6. Android事件总线分发库EventBus3.0的简单讲解与实践

    Android事件总线分发库EventBus的简单讲解与实践 导语,EventBus大家应该不陌生,EventBus是一款针对Android优化的发布/订阅事件总线.主要功能是替代Intent,Han ...

  7. Autofac解耦事件总线

    事件总线之Autofac解耦 事件总线是通过一个中间服务,剥离了常规事件的发布与订阅(消费)强依赖关系的一种技术实现.事件总线的基础知识可参考圣杰的博客[事件总线知多少] 本片博客不再详细概述事件总线 ...

  8. C# 事件总线 EventBus

    1. 引言 事件总线这个概念对你来说可能很陌生,但提到观察者(发布-订阅)模式,你也许就很熟悉.事件总线是对发布-订阅模式的一种实现.它是一种集中式事件处理机制,允许不同的组件之间进行彼此通信而又不需 ...

  9. 事件总线(Event Bus)

    事件总线(Event Bus)知多少 源码路径:Github-EventBus简书同步链接 1. 引言 事件总线这个概念对你来说可能很陌生,但提到观察者(发布-订阅)模式,你也许就很熟悉.事件总线是对 ...

随机推荐

  1. C# 获取当前打开的文件夹2

    这一个则比较投机,准确性不能保证,可以参考:   这个类获取当前进程的句柄:  public class MyProcess     {         private bool haveMainWi ...

  2. 两个变量交换的四种方法(Java) 七种方法(JS)

    两个变量交换的四种方法(Java)   对于两种变量的交换,我发现四种方法,下面我用Java来演示一下. 1.利用第三个变量交换数值,简单的方法. (代码演示一下) 1 class TestEV 2 ...

  3. 用HTTP协议传输媒体文件 学习

    用HTTP协议传输媒体文件可以分两个阶段,第一个阶段是Progressive Download(渐进式下载方式)阶段,第二个阶段是HTTP streaming(HTTP流化)阶段.其中,第一个阶段可以 ...

  4. Devexpress ASPxPivotGrid 按某列排序,以及把GrandTotal修改掉

    <div> <table width="100%" border="0" cellspacing="0" cellpadd ...

  5. ubuntu为python处理图片安装图片数据增强库imgaug

    1 依赖Required dependencies: six numpy scipy scikit-image (pip install -U scikit-image) OpenCV (i.e. c ...

  6. unity5 静态和动态cubmap

    一,静态cubemap: asserts窗口 右键->Create->Legacy->Cubemap,新建一个cubemap,命名为cubeMap,然后为其各面指定贴图,如图: 需要 ...

  7. [sql]mysql启停脚本

    写了个较为完善的mysql多实例的启动停止脚本. [root@lanny 3307]# cat mysql #!/bin/sh [ $# != 1 ]&&{ echo "US ...

  8. cpu降频问题

    cpu做为能耗很高的硬件,最近几年厂商在节能方面做了很多处理,在服务器运行时,基于负载情况可调节成节能模式,节省电能,副作用是cpu的频率会降低,导致应用程序性能降低. 有第三方统计,服务器规模达到万 ...

  9. [Linux]运维三十六计--腾讯两位大神的总结

    这里是腾讯两位大神梁定安.周小军总记得运维DBA三十六计,So有道理

  10. 对Android的恶意吐槽(勿看,有毒)

    CSDN博客:http://blog.csdn.net/niu_gao 我觉得android系统中有一个特恶心人的大败笔.就是这个大败笔造成了android系统的卡卡卡不停. 这个大败笔就是对acti ...