Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >自己实现事件总线-EventBus事件总线的使用

自己实现事件总线-EventBus事件总线的使用

作者头像
章为忠学架构
发布于 2018-08-27 06:25:13
发布于 2018-08-27 06:25:13
1.6K00
代码可运行
举报
文章被收录于专栏:AI大模型AI大模型
运行总次数:0
代码可运行

在C#中,我们可以在一个类中定义自己的事件,而其他的类可以订阅该事件,当某些事情发生时,可以通知到该类。这对于桌面应用或者独立的windows服务来说是非常有用的。但对于一个web应用来说是有点问题的,因为对象都是在web请求中创建的,而且这些对象生命周期都很短,因而注册某些类的事件是很困难的。此外,注册其他类的事件会使得类紧耦合。事件总线便可以用来解耦并重复利用应用中的逻辑。

事件总线带来的好处和引入的问题

好处比较明显,就是独立出一个发布订阅模块,调用者可以通过使用这个模块,屏蔽一些线程切换问题,简单地实现发布订阅功能。

坏处可能比较隐晦,但这些需要足够引起我们的重视

  • 大量的滥用,将导致逻辑的分散,出现问题后很难定位。
  • 没办法实现强类型,在编译的时候就发现问题。
  • 代码可读性有些问题,IDE无法识别这些协议,对IDE不友好。

总得来说,如果项目里面有大量的事件交互,那么还是可以通过EventBus来实现,否则还是推荐自己在模块内部实现观察者模式。

示例代码

所以今天介绍一个简单的事件总线,它是事件发布订阅模式的实现,让我们能在领域驱动设计(DDD)中以事件的弱引用本质对我们的模块和领域边界很好的解耦设计。

目前,所有的源代码已经提交到github 上,地址:https://github.com/weizhong1988/Weiz.EventBus

程序目录结构如下:

事件总线

事件总线是被所有触发并处理事件的其他类共享的单例对象。要使用事件总线,首先应该获得它的一个引用。下面有两种方法来处理:

订阅事件

触发事件之前,应该先要定义该事件。EventBus为我们提供了Subscribe 方法来订阅事件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        public void Subscribe<TEvent>(IEventHandler<TEvent> eventHandler) where TEvent : IEvent
        {            //同步锁
            lock (_syncObject)
            {                //获取领域模型的类型
                var eventType = typeof(TEvent);                //如果此领域类型在事件总线中已注册过
                if (_dicEventHandler.ContainsKey(eventType))
                {                    var handlers = _dicEventHandler[eventType];                    if (handlers != null)
                    {
                        handlers.Add(eventHandler);
                    }                    else
                    {
                        handlers = new List<object>
                        {
                            eventHandler
                        };
                    }
                }                else
                {
                    _dicEventHandler.Add(eventType, new List<object> { eventHandler });
                }
            }
        }

所以的事件都集成自IEvent,该类包含了类处理事件需要的属性。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 var sendEmailHandler = new UserAddedEventHandlerSendEmail(); var sendMessageHandler = new UserAddedEventHandlerSendMessage(); var sendRedbagsHandler = new UserAddedEventHandlerSendRedbags();
 Weiz.EventBus.Core.EventBus.Instance.Subscribe(sendEmailHandler);
 Weiz.EventBus.Core.EventBus.Instance.Subscribe(sendMessageHandler);
 //Weiz.EventBus.Core.EventBus.Instance.Subscribe<UserGeneratorEvent>(sendRedbagsHandler);
 Weiz.EventBus.Core.EventBus.Instance.Subscribe<OrderGeneratorEvent>(sendRedbagsHandler);

发布事件

对于事件源,则可以通过Publish 方法发布事件。触发一个事件很简单,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
     public void Publish<TEvent>(TEvent tEvent, Action<TEvent, bool, Exception> callback) where TEvent : IEvent
        {            var eventType = typeof(TEvent);            if (_dicEventHandler.ContainsKey(eventType) && _dicEventHandler[eventType] != null &&
                _dicEventHandler[eventType].Count > 0)
            {                var handlers = _dicEventHandler[eventType];                try
                {                    foreach (var handler in handlers)
                    {                        var eventHandler = handler as IEventHandler<TEvent>;
                        eventHandler.Handle(tEvent);
                        callback(tEvent, true, null);
                    }
                }                catch (Exception ex)
                {
                    callback(tEvent, false, ex);
                }
            }            else
            {
                callback(tEvent, false, null);
            }
        }

下面是发布事件的调用:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
            var orderGeneratorEvent = new OrderGeneratorEvent { OrderId = Guid.NewGuid() };

            System.Console.WriteLine("{0}下单成功", orderGeneratorEvent.OrderId);
          
            Weiz.EventBus.Core.EventBus.Instance.Publish(orderGeneratorEvent, CallBack);

定义处理事件

要处理一个事件,应该要实现IEventHandler接口,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    /// <summary>
    /// send email    /// </summary>
    public class UserAddedEventHandlerSendEmail : IEventHandler<UserGeneratorEvent>
    {        public void Handle(UserGeneratorEvent tEvent)
        {
            System.Console.WriteLine(string.Format("{0}的邮件已发送", tEvent.UserId));
        }
    }
处理多事件

在一个单一的处理句柄中,可以处理多个事件。这时,你应该为每个事件实现IEventHandler。比如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    /// <summary>
    /// red bags.    /// </summary>
    public class UserAddedEventHandlerSendRedbags : IEventHandler<UserGeneratorEvent>,IEventHandler<OrderGeneratorEvent>
    {        public void Handle(OrderGeneratorEvent tEvent)
        {
            System.Console.WriteLine(string.Format("{0}的下单红包已发送", tEvent.OrderId));
        }        public void Handle(UserGeneratorEvent tEvent)
        {
            System.Console.WriteLine(string.Format("{0}的注册红包已发送", tEvent.UserId));
        }
    }

最后

以上,就把事件总线介绍完了,完整的代码,请到github 上下载,这个只是EventBus 的简单实现,各位可以根据自己的实际场景和需求,优化修改。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-03-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 架构师精进 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
事件总线知多少(1)
源码路径:Github-EventBus 事件总线知多少(1) 事件总线知多少(2) 1. 引言 事件总线这个概念对你来说可能很陌生,但提到观察者(发布-订阅)模式,你也许就很熟悉。事件总线是对
圣杰
2018/01/11
1.5K0
事件总线知多少(1)
事件总线知多少(2)
源码路径:Github-EventBus 事件总线知多少(1) 事件总线知多少(2) 1.引言 之前的一篇文章事件总线知多少(1),介绍了什么是事件总线,并通过发布订阅模式一步一步的分析重构,形
圣杰
2018/01/11
1.2K0
事件总线知多少(2)
自己动手写事件总线(EventBus)
Android中存在各种通信场景,如`Activity`之间的跳转,`Activity`与`Fragment`以及其他组件之间的交互,以及在某个耗时操作(如请求网络)之后的callback回调等,互相之之间往往需要持有对方的引用,每个场景的写法也有差异,导致耦合性较高且不便维护。
达文西
2018/12/23
1K0
自己动手写事件总线(EventBus)
C# 如何实现一个事件总线
Event Bus(事件总线)是一种用于在应用程序内部或跨应用程序组件之间进行事件通信的机制。
郑子铭
2024/01/17
3130
C# 如何实现一个事件总线
造轮子之EventBus
前面基础管理的功能基本开发完了,接下来我们来优化一下开发功能,来添加EventBus功能。 EventBus也是我们使用场景非常广的东西。这里我会实现一个本地的EventBus以及分布式的EventBus。 分别使用MediatR和Cap来实现。
饭勺oO
2023/10/18
4240
造轮子之EventBus
CodeWF.EventBus:轻量级事件总线,让通信更流畅
EventBus(事件总线),用于解耦模块之间的通讯。本库(CodeWF.EventBus)适用于进程内消息传递(无其他外部依赖),与大家普遍使用的MediatR部分类似,但MediatR库侧重于ASP.NET Core设计使用,而本库也有点点优势:
沙漠尽头的狼
2024/06/10
2970
CodeWF.EventBus:轻量级事件总线,让通信更流畅
WPF中实现Eventbus
在开发Android或Vue前端的时候,我们可能数据产生后需要在多个页面接收,这时候可以用EventBus来实现,那么WPF开发能用EventBus吗?我没就来尝试一下!
码客说
2020/07/14
9550
浅入 ABP 系列(4):事件总线
这一篇将来学习 ABP 中的事件总线,然后结合在我们的基架项目中,逐渐构建一个完整的系统。
痴者工良
2021/04/26
1.1K0
微服务实战(二):落地微服务架构到直销系统(构建消息总线框架接口)
从上一篇文章大家可以看出,实现一个自己的消息总线框架是非常重要的内容,消息总线可以将界限上下文之间进行解耦,也可以为大并发访问提供必要的支持。
用户1910585
2018/08/02
6510
微服务实战(二):落地微服务架构到直销系统(构建消息总线框架接口)
大升级!支持CQRS|异步订阅发布-CodeWF.EventBus
事件总线,即EventBus,是一种解耦模块间通讯的强大工具。在CodeWF.EventBus库中,我们得以轻松实现CQRS模式,并通过清晰、简洁的接口进行事件订阅与发布。接下来,我们将详细探讨如何使用这个库来处理事件。
沙漠尽头的狼
2024/06/18
1940
大升级!支持CQRS|异步订阅发布-CodeWF.EventBus
微服务实战(四):落地微服务架构到直销系统(将生产者与消费者接入消息总线)
前一篇文章我们已经完成了基于RabbitMq实现的的消息总线,这篇文章就来看看生产者(订单微服务)与消费者(经销商微服务)如何接入消息总线实现消息的发送与消息的接收处理。
用户1910585
2018/08/02
6300
[项目更新] 集成RabbitMQ队列与EventBus总线
终于项目继续迭代更新了,在开源这两年多,也是感谢每一个支持Blog.Core项目的同学,同时也感谢每一个在生产环境中使用,并提出意见和建议的小伙伴,2,606个Star,是我们相互之间共同的努力和肯定,上边的这些都是我和各位使用者提出的需求,刚开始很快,越是到后边,开发起来越难,这里先说明几点问题:
老张的哲学
2022/04/11
1.1K0
[项目更新] 集成RabbitMQ队列与EventBus总线
发布订阅模式:使用 Go 实现简单的事件总线
事件驱动架构是计算机科学中一种高度可扩展的范例。它允许我们可以多方系统异步处理事件。
章为忠学架构
2020/01/22
6.5K2
CQRS+ES项目解析-Diary.CQRS
在《当我们在讨论CQRS时,我们在讨论些神马》中,我们讨论了当使用CQRS的过程中,需要关心的一些问题。其中与CQRS关联最为紧密的模式莫过于Event Sourcing了,CQRS与ES的结合,为我们构造高性能、可扩展系统提供了基本思路。本文将介绍 Kanasz Robert在《Introduction to CQRS》中的示例项目Diary.CQRS。
拓荒者IT
2019/09/23
7970
CQRS+ES项目解析-Diary.CQRS
DDD领域驱动设计总结和C#代码示例
DDD(领域驱动设计)是一种软件设计方法,它强调以业务领域为核心来驱动软件的设计和开发。
郑子铭
2024/05/10
4100
DDD领域驱动设计总结和C#代码示例
Guava - EventBus(事件总线)
Guava在guava-libraries中为我们提供了事件总线EventBus库,它是事件发布订阅模式的实现,让我们能在领域驱动设计(DDD)中以事件的弱引用本质对我们的模块和领域边界很好的解耦设计。
哲洛不闹
2018/09/14
1.5K0
Android事件总线(四)源码解析otto
Android事件总线(一)EventBus3.0用法全解析 Android事件总线(二)EventBus3.0源码解析 Android事件总线(三)otto用法全解析 前言 上一篇文章中讲到了ot
用户1269200
2018/02/01
7590
Android事件总线(四)源码解析otto
eShopOnContainers 知多少[5]:EventBus With RabbitMQ
事件总线这个概念对你来说可能很陌生,但提到观察者(发布-订阅)模式,你也许就很熟悉。事件总线是对发布-订阅模式的一种实现。它是一种集中式事件处理机制,允许不同的组件之间进行彼此通信而又不需要相互依赖,达到一种解耦的目的。
圣杰
2018/12/21
1K0
Vue3中如何自定义消息总线
在 Vue 开发中,组件之间的通信是一个常见的需求,无论是父组件向子组件传递数据,还是子组件向父组件传递数据,甚至是兄弟组件之间的数据交换。这些通信需求在构建复杂的 Vue 应用时尤为关键。
astonishqft
2024/05/31
2550
Vue3中如何自定义消息总线
Android面试之EventBus
众所周知,EventBus 是一款用在 Android 开发中的发布/订阅事件总线框架,基于观察者模式,将事件的接收者和发送者分开,简化了组件之间的通信操作,使用简单、效率高、体积小!
xiangzhihong
2022/11/30
6420
相关推荐
事件总线知多少(1)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验