前言

闲暇之余,简单写一个eventbus。

正文

什么是eventbus?

eventbus 是一个开源的发布订阅模式的框架,用于简化程序间不同组件的通信。

它允许不同组件间松耦合通信,组件之间不通过直接引用的方式,而是事件的方式进行消息传递。

下面进行代码演示:

首先是发布订阅,那么就应该有发布方法和订阅方法,因为是消息传递,那么就应该还有启动消费消息的方法。

public interface IEventBus : IDisposable
{
Task Publish<T>(T @event) where T : IntegrationEvent; Task Subscribe<T>(IIntegrationEventHandler<T> handler)
where T : IntegrationEvent; Task StartConsume();
}

大体我们要实现上面的功能。

然后我们可以定义事件的基础信息:

public class IntegrationEvent
{
public Guid Id { get; set; } public DateTime OccurredOn { get; set; } public IntegrationEvent()
{
Id = Guid.NewGuid();
OccurredOn = DateTime.Now;
}
}

比如说要有唯一的id,同时要有事件发生的时间。

订阅的话,那么需要指定处理的对象。

public interface IIntegrationEventHandler
{
} public interface IIntegrationEventHandler<in TIntegrationEvent> :
IIntegrationEventHandler where TIntegrationEvent : IntegrationEvent
{
Task Handler(TIntegrationEvent @event);
}

处理对象设计也很简单,就是需要创建一个有能够处理IntegrationEvent的对象即可。

这里很多人会疑惑,为什么很多框架的泛型接口类,往往会创建一个非泛型的接口。

这个其实是为了进一步抽象,方便做集合处理,下面将会介绍到。

然后就可以写一个内存型的eventbus。

public class InMemoryEventBus : IDisposable
{
private Dictionary<string, List<IIntegrationEventHandler>>
_dictionary = new Dictionary<string, List<IIntegrationEventHandler>>(); public async Task Publish<T>(T @event) where T : IntegrationEvent
{
var fullName = @event.GetType().FullName;
if (fullName == null)
{
return;
} var handlers = _dictionary[fullName]; foreach (var integrationEventHandler in handlers)
{
if (integrationEventHandler is IIntegrationEventHandler<T> handler)
{
await handler.Handler(@event);
}
}
} public async Task Subscribe<T>(IIntegrationEventHandler<T> handler)
where T : IntegrationEvent
{
var fullname = typeof(T).FullName;
if (fullname == null)
{
return;
} if (_dictionary.ContainsKey(fullname))
{
var handlers = _dictionary[fullname];
handlers.Add(handler);
}
else
{
_dictionary.Add(fullname, new List<IIntegrationEventHandler>()
{
handler
});
}
} public void Dispose()
{
// 移除相关连接等
}
}

里面实现了eventbus的基本功能。可以看到上面的_dictionary,里面就是IIntegrationEventHandler,

所以泛型接口会继承一个非泛型的接口,是为了进一步抽象声明,对一些集合处理是很方便的。

然后这里为什么没有直接继承Ieventbus呢? 而是实现eventbus的功能。

因为Ieventbus 其实是面向用户的,继承ieventbus只是一个门面,相当于适配器。

而InMemoryEventBus 是为了实现功能。

可以理解为InMemoryEventBus 是我们电脑主板、cpu等,然后我们只需要一个实现其接口的组件,从而和外部连接。

而不是整个内核系统和外部直连,那么我们可以使用InMemoryEventBusClient 作为这个组件。

public class InMemoryEventBusClient : IEventBus
{
private readonly InMemoryEventBus _eventBus; public InMemoryEventBusClient()
{
_eventBus = new InMemoryEventBus();
} public void Dispose()
{
_eventBus.Dispose();
} public async Task Publish<T>(T @event) where T : IntegrationEvent
{
await _eventBus.Publish(@event);
} public async Task Subscribe<T>(IIntegrationEventHandler<T> handler) where T : IntegrationEvent
{
await _eventBus.Subscribe(@handler);
} public Task StartConsume()
{
// 运行相关的消费
return Task.CompletedTask;
}
}

InMemoryEventBusClient 负责实现外部接口,InMemoryEventBus 负责实现功能。

从而达到解耦的目的。

同样的例子还有polly,这个框架应该很出名了,其中他里面就有很多衍生的组件,都是调用内核来适配其他框架定义的接口。

上面可以看到StartConsume什么都没有做,其功能被Publish给融合了。

只要publish就消费了。

如果我们扩展kafka的话,那么consume其实就是拉取数据然后消费,publish其实就是推向kafka,中间就是序列号和反序列话的过程。

eventbus 完善篇后续再补。

简单写一个eventbus的更多相关文章

  1. extjs开发———用extJS简单写一个饼状图

    先上效果图: js编写部分简单如下,先插入一个模块,然后给模块中添加内容. var myChart1 = echarts.init(document.getElementById('myChart1' ...

  2. 用vue和layui简单写一个响应式数据展示表

    在创建项目之前,先把我们需要的文件打包处理 <!DOCTYPE html> <html lang="en"> <head> <meta c ...

  3. 【转】用C写一个简单病毒

    [摘要]在分析病毒机理的基础上,用C语言写了一个小病毒作为实例,用TURBOC2.0实现. [Abstract] This paper introduce the charateristic of t ...

  4. 用Python写一个简单的Web框架

    一.概述 二.从demo_app开始 三.WSGI中的application 四.区分URL 五.重构 1.正则匹配URL 2.DRY 3.抽象出框架 六.参考 一.概述 在Python中,WSGI( ...

  5. 如何写一个简单的http服务器

    最近几天用C++写了一个简单的HTTP服务器,作为学习网络编程和Linux环境编程的练手项目,这篇文章记录我在写一个HTTP服务器过程中遇到的问题和学习到的知识. 服务器的源代码放在Github. H ...

  6. 如何写一个简单的shell

    如何写一个简单的shell 看完<UNIX环境高级编程>后我就一直想写一个简单的shell来作为练习,因为有事断断续续的写了好几个月,如今写了差不多来总结一下. 源代码放在了Github: ...

  7. 分享:计算机图形学期末作业!!利用WebGL的第三方库three.js写一个简单的网页版“我的世界小游戏”

    这几天一直在忙着期末考试,所以一直没有更新我的博客,今天刚把我的期末作业完成了,心情澎湃,所以晚上不管怎么样,我也要写一篇博客纪念一下我上课都没有听,还是通过强大的度娘完成了我的作业的经历.(当然作业 ...

  8. 用qpython3写一个最简单的发送短信的程序

    到目前为止并没有多少手机应用是用python开发的,不过qpython可以作为一个不错的玩具推荐给大家来玩. 写一个最简单的发送短信的程序,代码如下: #-*-coding:utf8;-*- #qpy ...

  9. 写一个ajax程序就是如此简单

    写一个ajax程序就是如此简单 ajax介绍: 1:AJAX全称为Asynchronous JavaScript and XML(异步JavaScript和XML),指一种创建交互式网页应用的网页开发 ...

  10. 自己动手写一个简单的(IIS)小型服务器

    因为第一次在博客园发表随笔,不太会用,这个笔记是我之前在印象笔记中写好的,然后直接copy过来,有兴趣自己做一个IIS服务器的小伙伴们可以参照下面的流程做一次,也可以叫我要源代码,不过要做完,我觉得花 ...

随机推荐

  1. Jenkins Pipeline:根据参数设置环境变量

    pipeline { agent any environment { //以上自定义的参数 project = "$params.PROJECT" } stages { stage ...

  2. mybatis批量插入的四种方式

    一.循环插入 public void insert(List<User> userList) { userList.forEach(user -> userDao.insert(us ...

  3. 序列图 时序图 PlantUML vscode drawio 制作

    序列图 时序图 PlantUML vscode drawio 制作 需求 最近发现 序列图 很多文档都用到,而且很好用.经过研究用vscode,idea都可以编写.这里用vscode编写比较简单. d ...

  4. 日常办公——Excel中重复打印标题的设置

    打印预览时,所在数据行或列不能显示在同一页,在打印区域之外还有内容,为了方便阅读,可使用顶端标题行重复或左端标题行重复,具体方法如下: 按顺序操作,完成后点击确定即完成操作.

  5. Sub-process /usr/bin/dpkg returned an error code (1)问题

    在用apt-get安装软件包的时候遇到E: Sub-process /usr/bin/dpkg returned an error code (1)问题,解决方法如下: cd /var/lib/dpk ...

  6. 主题 3 编辑器(Vim)

    主题 3 编辑器(Vim) 编辑器 (Vim) · the missing semester of your cs education (missing-semester-cn.github.io) ...

  7. Android混淆后的bug日志通过mapping文件找对应行号

    背景 由于项目中提测以及线上的apk都是经过混淆处理的,因此拿到日志后也无法正常查看崩溃日志的行号 这个原因是因为混淆了文件,输出的日志是对应不上源文件的,为了正确找到行号需要用到mapping.tx ...

  8. Ubuntu下安装Android Studio

    一.系统环境 二.安装源文件 Android Studio 4.2.2:android-studio-ide-202.7486908-linux.tar.gz Java SE Development ...

  9. XSS 从 PDF 中窃取数据

    XSS 从 PDF 中窃取数据 将服务器端 XSS 注入到动态生成的 PDF 中 在 hack the box 的 Book 机器(Scripting Track)上,我遇到了一个 Web 应用程序, ...

  10. 记录-Vue移动端日历设计与实现

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 工作中遇到一个需求是根据日历查看某一天/某一周/某一月的睡眠报告,但是找了好多日历组件都不是很符合需求,只好自己手写一个日历组件,顺便记录 ...