zoukankan      html  css  js  c++  java
  • 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");
            }
        }

    关于服务总线的实现方式

    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上表现也很不错!

    自己也骄傲一次,呵呵!

     回到目录

  • 相关阅读:
    MySQL数据库的常用命令
    函数返回 局部变量问题
    几种网络I/O模型
    socket的select模型【摘】
    Linux Bash Shell入门教程【转载】
    Shell学习【转】
    unicode 2 utf8 [转]
    linux下多线程的创建与等待详解 【转载】
    运算(93&-8)的结果
    一道腾讯的面试题,关于a和&a
  • 原文地址:https://www.cnblogs.com/lori/p/7158071.html
Copyright © 2011-2022 走看看