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

    自己也骄傲一次,呵呵!

     回到目录

  • 相关阅读:
    leetcode 48. Rotate Image
    leetcode 203. Remove Linked List Elements 、83. Remove Duplicates from Sorted List 、82. Remove Duplicates from Sorted List II(剑指offer57 删除链表中重复的结点) 、26/80. Remove Duplicates from Sorted ArrayI、II
    leetcode 263. Ugly Number 、264. Ugly Number II 、313. Super Ugly Number 、204. Count Primes
    leetcode 58. Length of Last Word
    安卓操作的一些问题解决
    leetcode 378. Kth Smallest Element in a Sorted Matrix
    android studio Gradle Build速度加快方法
    禁用gridview,listview回弹或下拉悬停
    Android Studio找不到FragmentActivity类
    安卓获取ListView、GridView等滚动的距离(高度)
  • 原文地址:https://www.cnblogs.com/lori/p/7158071.html
Copyright © 2011-2022 走看看