DotNetCore跨平台~服务总线_事件总线的重新设计

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介:

理论闲话

之前在.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跨平台~服务总线_事件总线的重新设计,如需转载请自行联系原博主。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
1月前
|
开发工具 C语言 git
【嵌入式开源库】MultiButton的使用,简单易用的事件驱动型按键驱动模块
【嵌入式开源库】MultiButton的使用,简单易用的事件驱动型按键驱动模块
|
网络协议 Android开发 数据安全/隐私保护
HarmonyOS系统中内核实现MQTT协议开发的方法
大家好,今天主要来聊一聊,如何使用鸿蒙开始实现MQTT协议开发的方法
270 1
HarmonyOS系统中内核实现MQTT协议开发的方法
|
消息中间件 API
HarmonyOS系统内核中消息队列的实现
大家好,今天主要来聊一聊,如何使用HarmonyOS开发实现消息队列。
214 0
HarmonyOS系统内核中消息队列的实现
|
存储 JSON 物联网
HarmonyOS系统中内核实现智慧物流控制的方法
大家好,今天主要和大家聊一聊,如何使用鸿蒙系统实现智能物流的开发.
175 0
HarmonyOS系统中内核实现智慧物流控制的方法
|
开发工具 芯片 开发者
5.6 芯片SDK开发:硬件无关组件相关开发|学习笔记
快速学习5.6 芯片SDK开发:硬件无关组件相关开发
115 0
5.6 芯片SDK开发:硬件无关组件相关开发|学习笔记
|
编译器 C语言
QT应用编程: QtCreate编译部署开源音视频框架模块QtAV
QT应用编程: QtCreate编译部署开源音视频框架模块QtAV
172 0
QT应用编程: QtCreate编译部署开源音视频框架模块QtAV
|
存储 IDE API
HarmonyOS(鸿蒙)应用程序包结构介绍
HarmonyOS(鸿蒙)应用程序包结构介绍
276 0
HarmonyOS(鸿蒙)应用程序包结构介绍
|
物联网 调度 开发工具
技术解码 | YoC组件开发系列一:如何向OCC发布芯片产品组件
技术解码栏目:是面向开发者详细解读芯片开放社区(OCC)上关于处理器、芯片、基础软件平台、集成开发环境及应用开发平台的相关技术,方便开发者学习及快速上手,提升开发效率。
377 0
技术解码 | YoC组件开发系列一:如何向OCC发布芯片产品组件
|
jenkins 物联网 测试技术
RISC-V生态全景解析(十一):YoC组件介绍系列一: CSI组件
编辑语: 芯片开放社区(OCC)面向开发者推出RISC-V系列内容,通过多角度、全方位解读RISC-V,系统性梳理总结相关理论知识,构建RISC-V知识图谱,促进开发者对RISC-V生态全貌的了解。
555 0
RISC-V生态全景解析(十一):YoC组件介绍系列一: CSI组件
|
IDE 开发工具
RISC-V MCU开发 (十一):跨内核工程转换
大多数嵌入式工程师使用Keil进行开发,但Keil目前不支持RISC-V内核,只支持ARM内核。MounRiver® Studio(MRS)同时支持两种内核,为了方便工程师从ARM内核迁移至RISC-V内核,MRS增加了Keil工程转换的功能。
RISC-V MCU开发 (十一):跨内核工程转换