回到目录

理论闲话

之前在.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. 【Java并发系列03】ThreadLocal详解

    img { border: solid 1px } 一.前言 ThreadLocal这个对象就是为多线程而生的,没有了多线程ThreadLocal就没有存在的必要了.可以将任何你想在每个线程独享的对象 ...

  2. Swift 入门之简单语法(二)

    可选项判断 由于可选项的内容可能为 nil,而一旦为 nil 则不允许参与计算 因此使用中,经常需要判断可选项的内容是否为 nil 单个可选项判断 let url = NSURL(string: &q ...

  3. stm32之IIC通信协议

    I2C(IIC,Inter-Integrated Circuit),两线式串行总线,由PHILIPS公司开发用于连接微控制器及其外围设备. 它是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数 ...

  4. java基础之位运算

    java中常见的位运算符:&(逻辑与) |(逻辑或) ~(取反) ^(逻辑异或) >>(右移) <<(左移) >>>(无符号右移) &(逻辑与 ...

  5. 简易-五星评分-jQuery纯手写

    超级简单的评分功能,分为四个步骤轻松搞定: 第一步: 引入jquery文件:这里我用百度CDN的jquery: <script src="http://apps.bdimg.com/l ...

  6. Eclipse用法:自动生成get和set方法

      方法一 Java的类中,除了常量声明为静态且公有的,一般的对象数据作用域,都是声明为私有的.这样做能保护对象的属性不会被随意改变,调试的时候也会方便很多:在类的公有方法中大一个调用栈就能看到哪里改 ...

  7. Html5模拟通讯录人员排序(sen.js)

    // JavaScript Document var PY_Json_Str = ""; var PY_Str_1 = ""; var PY_Str_2 = & ...

  8. Python函数之简单总结

    函数的定义 Python的函数定义使用关键字def,如定义一个返回绝对值的函数my_abs def my_abs(x): if x>=0: return x else: return -x 函数 ...

  9. CentOS 安装数据库笔记

    1.配置YUM源 # 下载mysql源安装包 shell.noarch.rpm # 安装mysql源 shell.noarch.rpm 检查mysql源是否安装成功 shell> yum rep ...

  10. 对js运算符“||”和“&&”的总结

    首先出个题: 如图: 假设对成长速度显示规定如下: 成长速度为5显示1个箭头: 成长速度为10显示2个箭头: 成长速度为12显示3个箭头: 成长速度为15显示4个箭头: 其他都显示都显示0各箭头. 用 ...