回到目录

理论闲话

之前在.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");
}
}

关于服务总线的实现方式

  1. RedisBus基于redis进行存储,事件发布后,所有相关处理程序被回调,要求事件和处理程序是可序列化的
  2. MemoryBus基于应用服务器缓存进行存储,所有相关处理程序被回调,集群环境不是很适合
  3. IoCBus基于redis作为事件字典,处理程序由IoC容器进行注入,使用场合更广

IoCBus实现思想与组成

  1. 应该有一个存储事件与处理程序对应关系的字典
  2. 字典应该被持久化到中间件里
  3. 应该有个容器,去管理字典值与处理程序的关系

代码实现

数据变更的定义

     /// <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跨平台~服务总线_事件总线的重新设计的更多相关文章

  1. 【bird-java】分布式服务间的事件总线EventBus

    什么是EventBusEventBus是对发布-订阅模式的一种实现.其以一种非常优雅的方式实现了组件间的解耦与通信,在Android开发.DDD等领域都有非常广泛的应用. 事件流大致如下: Produ ...

  2. DotNetCore跨平台~文章索引~永久更新

    本索引目录主要包括仓储大叔对dotnet core架构的研究与知识积累,从2016年开始进行撰写,到今天已经有一年多了,其中有一些小知识,小技巧,小应用,希望给大家在开发时一些启发,也希望dotnet ...

  3. ASP.NET Core Web API下事件驱动型架构的实现(三):基于RabbitMQ的事件总线

    在上文中,我们讨论了事件处理器中对象生命周期的问题,在进入新的讨论之前,首先让我们总结一下,我们已经实现了哪些内容.下面的类图描述了我们已经实现的组件及其之间的关系,貌似系统已经变得越来越复杂了. 其 ...

  4. Autofac解耦事件总线

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

  5. RabbitMQ的事件总线

    RabbitMQ的事件总线 在上文中,我们讨论了事件处理器中对象生命周期的问题,在进入新的讨论之前,首先让我们总结一下,我们已经实现了哪些内容.下面的类图描述了我们已经实现的组件及其之间的关系,貌似系 ...

  6. 重温.NET下Assembly的加载过程 ASP.NET Core Web API下事件驱动型架构的实现(三):基于RabbitMQ的事件总线

    重温.NET下Assembly的加载过程   最近在工作中牵涉到了.NET下的一个古老的问题:Assembly的加载过程.虽然网上有很多文章介绍这部分内容,很多文章也是很久以前就已经出现了,但阅读之后 ...

  7. 浅入 ABP 系列(4):事件总线

    浅入 ABP 系列(4):事件总线 版权护体作者:痴者工良,微信公众号转载文章需要 <NCC开源社区>同意. 目录 浅入 ABP 系列(4):事件总线 事件总线 关于事件总线 为什么需要这 ...

  8. Android事件总线

    Android中Activity.Service.Fragment之间的相互通信比较麻烦,主要有以下一些方法: (1)使用广播,发送者发出广播,接收者接收广播后进行处理: (2)使用Handler和M ...

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

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

随机推荐

  1. laravel5.2之logout注销账号无效

    问题描述:laravel5.2的框架,使用框架auth用户认证后,进行账号注销退出的时候,无法实现. 只有清除浏览器缓存,才能实现账号退出. 解决办法: 改变路由 Route::get('auth/l ...

  2. 利用nodeJs来安装less以及编译less文件为css文件

    NodeJs 使用nodejs安装less以及编译less文件为css文件 首先下载nodeJs的安装包,按照步骤,安装nodejs. 链接:http://pan.baidu.com/s/1dEsqY ...

  3. JqueryEasyUI-从入门到精通-第一天

    PS:本教程暂时不提供源码,自己动手写写会记得更牢固哦 Parser(解析器) 对象的属性和方法: 使用: 效果:

  4. laravel 服务容器实现原理

    前言 通过实现laravel 框架功能,以便深入理解laravel框架的先进思想. 什么是服务容器 服务容器是用来管理类依赖与运行依赖注入的工具.Laravel框架中就是使用服务容器来实现 ** 控制 ...

  5. 高性能迷你React框架anu在低版本IE的实践

    理想是丰满的,现实是骨感的,react早期的版本虽然号称支持IE8,但是页面总会不自觉切换到奇异模式下,导致报错.因此必须让react连IE6,7都支持,这才是最安全.但React本身并不支持IE6, ...

  6. 日常踩坑 searter

    目录 es7中的async, await Django生成二维码并转为base64 Django配置404页面 很傻逼的坑 no module named pil 其他 es7中的async, awa ...

  7. python 标准库 -- threading

    threading : 提高对网络端口的读写效率. threading.Thread.start() 执行线程操作 threading.Thread.run() 执行线程操作 threading.Th ...

  8. oracle删除数据后表空间仍过大问题解决方法

    -----亲测有效------- --一.备份原始数据库库--1.备份空表--在plsql里面执行一下这句话 然后把结果集 再执行一把 再导数据select 'alter table '||table ...

  9. 2017最新xcode打包APP详细图文

    网上的xcode打包ipa教程大多太旧而且又不完整,所以整理了一个最新的完整详细的xcode打包APP的图文教程分享给小白到大神路上前进的你我. xcode打包IPA包之前先申请iOS证书,然后导入证 ...

  10. linux 权限字母含义

    查看某一文件夹下所有文件夹的权限情况:ls -l分别是:所有者(user)-所有者(user)-其他人(other)r 表示文件可以被读(read)w 表示文件可以被写(write)x 表示文件可以被 ...