DotNetCore跨平台~服务总线_事件总线的重新设计
理论闲话
之前在.netFramework平台用的好好的,可升级到.net core平台之后,由于不再需要二进制序列化,导致咱们的事件机制遇到了问题,之前大叔的事件一直是将处理程序序列化后进行存储的,处理存储的参数为事件源,一个事件源可以由多个处理程序订阅,当事件源被发布时,这些被序列化的代码段会被回调执行,这是大叔之前的思路,在RedisBus和MemoryBus里已经得到了实现,读过大叔源代码的同学应该有所了解了。
事件源和处理程序
/// <summary>
/// 事件源
/// </summary>
public class CreateUserCommand : BusData
{
public string UserName { get; set; }
} /// <summary>
/// 事件处理程序
/// </summary>
public class CreateUserCommandHandler : IBusHandler<CreateUserCommand>
{
public void Handle(CreateUserCommand evt)
{
LoggerFactory.CreateLog().Logger_Debug(evt.UserName);
Console.WriteLine("CreateUserCommandHandler");
}
}
关于服务总线的实现方式
- RedisBus基于redis进行存储,事件发布后,所有相关处理程序被回调,要求事件和处理程序是可序列化的
- MemoryBus基于应用服务器缓存进行存储,所有相关处理程序被回调,集群环境不是很适合
- IoCBus基于redis作为事件字典,处理程序由IoC容器进行注入,使用场合更广
IoCBus实现思想与组成
- 应该有一个存储事件与处理程序对应关系的字典
- 字典应该被持久化到中间件里
- 应该有个容器,去管理字典值与处理程序的关系
代码实现
数据变更的定义
/// <summary>
/// redis key
/// </summary>
const string ESBKEY = "IoCESBBus";
/// <summary>
/// redis事件字典
/// </summary>
IDatabase redis = RedisManager.Instance.GetDatabase();
/// <summary>
/// 模式锁
/// </summary>
private static object _objLock = new object();
/// <summary>
/// 对于事件数据的存储,目前采用内存字典
/// </summary>
private readonly IContainer container = new AutofacContainer();
事件的统一订阅
public void SubscribeAll()
{
var types = AssemblyHelper.GetTypesByInterfaces(typeof(IBusHandler<>));
Dictionary<string, List<string>> keyDic = new Dictionary<string, List<string>>();
foreach (var item in types)
{
if (!item.IsGenericParameter)
{ TypeInfo typeInfo = IntrospectionExtensions.GetTypeInfo(item); foreach (var t in typeInfo.GetMethods().Where(i => i.Name == "Handle"))
{
//ioc name key
var eventKey = t.GetParameters().First().ParameterType.Name;
var key = t.GetParameters().First().ParameterType.Name + "_" + item.Name;
//eventhandler
var inter = typeof(IBusHandler<>).MakeGenericType(t.GetParameters().First().ParameterType);
container.Register(inter, item, key); if (keyDic.ContainsKey(eventKey))
{
var oldEvent = keyDic[eventKey];
oldEvent.Add(key);
}
else
{
var newEvent = new List<string>();
newEvent.Add(key);
keyDic.Add(eventKey, newEvent);
}
}
}
//redis存储事件与处理程序的映射关系
foreach (var hash in keyDic)
redis.HashSet(
ESBKEY,
hash.Key.ToString(),
JsonConvert.SerializeObject(hash.Value)); } }
事件的发布,相关处理程序会从容器中取出,并执行它们的Handler方法
public void Publish<TEvent>(TEvent @event)
where TEvent : class, IBusData
{
var keyArr = JsonConvert.DeserializeObject<List<string>>(redis.HashGet(ESBKEY, typeof(TEvent).Name));
foreach (var key in keyArr)
{
var item = container.ResolveNamed<IBusHandler<TEvent>>(key);
item.Handle(@event);
} }
说到这里,大叔的服务总线的IoC实现方式就算是完成了,经过测试后,在.net core上表现也很不错!
自己也骄傲一次,呵呵!
DotNetCore跨平台~服务总线_事件总线的重新设计的更多相关文章
- 【bird-java】分布式服务间的事件总线EventBus
什么是EventBusEventBus是对发布-订阅模式的一种实现.其以一种非常优雅的方式实现了组件间的解耦与通信,在Android开发.DDD等领域都有非常广泛的应用. 事件流大致如下: Produ ...
- DotNetCore跨平台~文章索引~永久更新
本索引目录主要包括仓储大叔对dotnet core架构的研究与知识积累,从2016年开始进行撰写,到今天已经有一年多了,其中有一些小知识,小技巧,小应用,希望给大家在开发时一些启发,也希望dotnet ...
- ASP.NET Core Web API下事件驱动型架构的实现(三):基于RabbitMQ的事件总线
在上文中,我们讨论了事件处理器中对象生命周期的问题,在进入新的讨论之前,首先让我们总结一下,我们已经实现了哪些内容.下面的类图描述了我们已经实现的组件及其之间的关系,貌似系统已经变得越来越复杂了. 其 ...
- Autofac解耦事件总线
事件总线之Autofac解耦 事件总线是通过一个中间服务,剥离了常规事件的发布与订阅(消费)强依赖关系的一种技术实现.事件总线的基础知识可参考圣杰的博客[事件总线知多少] 本片博客不再详细概述事件总线 ...
- RabbitMQ的事件总线
RabbitMQ的事件总线 在上文中,我们讨论了事件处理器中对象生命周期的问题,在进入新的讨论之前,首先让我们总结一下,我们已经实现了哪些内容.下面的类图描述了我们已经实现的组件及其之间的关系,貌似系 ...
- 重温.NET下Assembly的加载过程 ASP.NET Core Web API下事件驱动型架构的实现(三):基于RabbitMQ的事件总线
重温.NET下Assembly的加载过程 最近在工作中牵涉到了.NET下的一个古老的问题:Assembly的加载过程.虽然网上有很多文章介绍这部分内容,很多文章也是很久以前就已经出现了,但阅读之后 ...
- 浅入 ABP 系列(4):事件总线
浅入 ABP 系列(4):事件总线 版权护体作者:痴者工良,微信公众号转载文章需要 <NCC开源社区>同意. 目录 浅入 ABP 系列(4):事件总线 事件总线 关于事件总线 为什么需要这 ...
- Android事件总线
Android中Activity.Service.Fragment之间的相互通信比较麻烦,主要有以下一些方法: (1)使用广播,发送者发出广播,接收者接收广播后进行处理: (2)使用Handler和M ...
- 事件总线(Event Bus)知多少
源码路径:Github-EventBus 简书同步链接 1. 引言 事件总线这个概念对你来说可能很陌生,但提到观察者(发布-订阅)模式,你也许就很熟悉.事件总线是对发布-订阅模式的一种实现.它是一种集 ...
随机推荐
- React学习小结(三)
一.React数据的传输 1.属性和状态是react中数据传递的载体 2.属性是声明以后不允许被修改的东西 3.属性只能在组件初始化的时候声明并传入组件内部,并且在组件内部通过this.props获取 ...
- Python教程(2.4)——字符串
2.2节讲过,Python中有字符串类型.在Python中,字符串用'或"括起,例如'abc'."qwerty"等都是字符串.注意'和"并不是字符串的内容. A ...
- HTML5笔记3——Web Storage和本地数据库
上一篇:HTML5笔记2——HTML5音/视频标签详解 Web Storage概述 在HTML5中,除了Canvas元素之外,另一个新增的非常重要的功能是可以再客户端本地保存数据的Web Storag ...
- Java常用类之【日期相关类】
一.日期类 Java语言提供了2个类来处理日期 Date类 Date类以毫秒来表示特定的日期 构造方法 Date date = new Date(); System.out.println(date) ...
- jQuery UI 入门之实用实例
jQuery UI 入门 jQuery UI 简介 jQuery UI 是一个建立在 jQuery JavaScript 库上的小部件和交互库,您可以使用它创建高度交互的 Web 应用程序.无论您是创 ...
- a标签点击之后有个虚线边框,怎么去掉
1.行内处理方式1 <a hidefocus="true" href="#"></a> 2.行内处理方式2,让a标签获得焦点就失去焦点, ...
- 网购的一套UI代码的始末
引言: 一个商业项目的需要,又因为时间紧迫的关系,准备购买一套简洁,易用,可定制化强的UI,经过对国内外多家UI产品进行了对比, 包括:FineUI, EasyUI, EXT.NET, EXTJS, ...
- 提高java编程质量 - (二)取余用偶判断,不要用奇判断
取余判断原则:取余用偶判断,不要用奇判断 先看一个 程序: package com.test; import java.util.Scanner; public class t1 { public s ...
- ajax基础知识、用ajax做登录页面、用ajax验证用户名是否可用、ajax动态调用数据库
1.ajax的基础知识 ajax是结合了jquery.php等几种技术延伸出来的综合运用的技术,不是新的内容.ajax也是写在<script>标签里面的. 如果使用ajax一定是要有1个处 ...
- 用Emacs收发邮件
使用Emacs,将尽可能多的工作放到Emacs中来完成,这样可以提高工作效率. 1.安装必要的LISP插件和程序 $sudo apt-get install stunnel4 $sudo apt-ge ...