事件总线demo

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

1、定义相关的接口:

  A  事件接口

 1 public interface IDomainEvent
 2     {
 3         DateTime OccurredOn();
 4
 5         /// <summary>
 6         /// 设置为已读
 7         /// </summary>
 8         /// <returns></returns>
 9         void Read();
10
11         /// <summary>
12         /// 是否已读
13         /// </summary>
14         bool IsRead { get; }
15     }

  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();
        }
    }
时间: 2024-10-05 21:15:25

事件总线demo的相关文章

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

官方demo见  https://github.com/square/otto 注意自己该编译版本为2.3以上,默认的1.6不支持match_parent属性,导致布局文件出错. 另外需要手动添加android-support-v4和otto到自己的libs文件夹. 主要代码逻辑: 1,在主页面点clear按钮,发布两个事件并传递对象. 2,然后LocationHistoryFragment接收事件对象,并处理. 1,BusProvider提供一个全局唯一的Bus实例对象 调用的时候使用MyPr

事件总线框架---Otto

我们假设这样一种业务场景,现在在做一款及时聊天应用,我们在聊天页面进行收发信息,同时也要实时更新前一页面的聊天记录,这时我们该如何去实现?说说我以前的实现策略,我使用的是广播接收器BroadCastReceiver,在接收和发送消息的时候就不停去发送广播,然后在需要实时更新的地方进行接收更新.实现的思想比较简单,也不存在代码上的耦合问题,但是有个弊端.弊端就是需要去在很多地方实现BroadCastRecevier,代码虽不算冗余,但比较多,看起来很是不爽. 今天为大家介绍的Otto,就能彻底解决

事件总线(Event Bus)

事件总线(Event Bus)知多少 源码路径:Github-EventBus简书同步链接 1. 引言 事件总线这个概念对你来说可能很陌生,但提到观察者(发布-订阅)模式,你也许就很熟悉.事件总线是对发布-订阅模式的一种实现.它是一种集中式事件处理机制,允许不同的组件之间进行彼此通信而又不需要相互依赖,达到一种解耦的目的. 我们来看看事件总线的处理流程: 了解了事件总线的基本概念和处理流程,下面我们就来分析下如何去实现事件总线. 2.回归本质 在动手实现事件总线之前,我们还是要追本溯源,探索一下

AndroidEventBus(事件总线)了解+实战体验

转载请注明出处:http://blog.csdn.net/woshizisezise/article/details/51225186 大家好,今天咱们来说说本人最近使用到的一个新的开源工具类,也就是今天的主人公AndroidEventBus,叫做事件总线,刚开始看到这个名字的时候我以为就是之前使用到的EventBus,于是乎好奇的我就接着研究了一下,果然它是类似EventBus的消息处理机制,提供了更好的使用性,我便希望把它集成到我正在开发的工程里,因为工程较大以及代码较为繁琐,我不敢轻易的集

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

最近再看eventbus相关代码,首先从使用开始,后期再从源码角度分析eventbus.使用Demo后期公布到github上去. 使用的框架地址:https://github.com/bboyfeiyu/AndroidEventBus Sticky 事件 使用例子: 1,首先每个Activity或者fragement都要进行eventBus的注册和反注册. 发送sticky事件的activity: 1 package com.example.mysimpleeventbus; 2 import

Android EventBus事件总线剖析

概述 EventBus是一款针对Android优化的发布/订阅事件总线.主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息. 它是一个基于观察者模式的事件发布/订阅框架,开发者可以通过极少的代码去实现多个模块之间的通信,而不需要以层层传递接口的形式去单独构建通信桥梁.从而降低因多重回调导致的模块间强耦合,同时避免产生大量内部类.它拥有使用方便,性能高,接入成本低和支持多线程的优点,实乃模块解耦.代码重构必备良药.

事件总线(Event Bus)知多少(转)

1. 引言 事件总线这个概念对你来说可能很陌生,但提到观察者(发布-订阅)模式,你也许就很熟悉.事件总线是对发布-订阅模式的一种实现.它是一种集中式事件处理机制,允许不同的组件之间进行彼此通信而又不需要相互依赖,达到一种解耦的目的. 我们来看看事件总线的处理流程: 了解了事件总线的基本概念和处理流程,下面我们就来分析下如何去实现事件总线. 2.回归本质 在动手实现事件总线之前,我们还是要追本溯源,探索一下事件的本质和发布订阅模式的实现机制. 2.1.事件的本质 我们先来探讨一下事件的概念.都是读

Android 开源项目android-open-project工具库解析之(二) 高版本向低版本兼容,多媒体相关,事件总线(订阅者模式),传感器,安全,插件化,文件

六.Android 高版本向低版本兼容 ActionBarSherlock 为Android所有版本提供统一的ActionBar,解决4.0以下ActionBar的适配问题 项目地址:https://github.com/JakeWharton/ActionBarSherlock Demo地址:https://play.google.com/store/apps/details?id=com.actionbarsherlock.sample.demos APP示例:太多了..现在连google都

事件总线OTTO(助Android深层次解耦——跟回调说拜拜)

<! -- http://blog.csdn.net/yuanyang5917/article/details/45482457 -- > 事件总线框架 针对事件提供统一订阅,发布以达到组件间通信的解决方案. 官方定义: Otto is an event bus designed to decouple different parts of your application while still allowing them to communicate efficiently. 原理 观察者