• ABP之事件总线(4)


    在上一篇的随笔中,我们已经初步完成了EventBus,但是EventBus中还有诸多的问题存在,那么到底有什么问题呢,接下来我们需要看一看ABP中的源码是如何定义EventBus的。

    1.第一个点

    在ABP中提供了对Action类型的支持,而我们的自己定义的类中只是针对继承了IEventHandler的接口的类

    2.第二个点

    在ABP中使用了线程安全的ConcurrentDictionary来存放映射关系,因为EventBus作为一个单例存在,这是必须要考虑的。ConcurrentDictionary虽然保证了字典的线程安全,但是并不能保证List的线程安全,可能存在同一时间同时插入相同的Handler,所以在上面的方法中使用了加锁的方式。

    3.第三个点

     从上面的源码中,我们可以看出EventBus使用了反射和容器(CastleWindsor)注入的方式触发,其实要实现完全解耦,实现灵活可配置,反射是一项必不可少的技术,但是凡事都都是讲究一个度,我们知道反射的缺点就是性能消耗比较大,随着反射技术的发展,反射的速度已经提升了许多,但是相对于直接调用,那还是存在一定的差距。但是只要讲究合理度,损耗一部分性能实现良好的系统,这是明智的。在上一篇随笔中,我们的所有的类型包括EventData和Eventhandler全部是使用的是反射的方式实现的,可想而知,这是消耗性能最大的,而在ABP中采用了加入的容器的方式,这将改善性能问题。其实还是那句话,容器这种接触耦合的方式还是离不开反射技术在里面。在Castle Windsor的源码中,它同样是维护了一个字典,只是将部分类通过反射的方式得到,来优化完全使用反射获取对象的方式。

    4.第四个点

    加入了异步的方式触发事件,通过重新开启一个线程的方式,提高执行的速度。

     首先来完善第一个问题,其实在事件总线最开始的时候我们已经尝试定义了一个统一的Handler只不过那个Handler定义的有点过头了。。。。,这个我们可以参照一下ABP的源码中ActionEventHandler中的定义

      internal class ActionEventHandler<TEventData> :IEventHandler<TEventData> where TEventData:EventData
        {
            /// <summary>
            /// Action委托具有一个TEventData类型的参数
            /// </summary>
            public Action<TEventData> Action { get; private set; }
            /// <summary>
            /// 因为就是为了统一创建Handler所以处理逻辑是通过构造函数传入而不是直接在Handle()方法中写死
            /// </summary>
            /// <param name="handler"></param>
            public ActionEventHandler(Action<TEventData> handler)
            {
                Action = handler;
            }
            public void Handle(TEventData evetData)
            {
                Action(evetData);
            }
        }

     我们在上一篇定义的Mouse类中,将我们的ActionHandler触发,简单的测试一下

     public void Come()
            {
                new ActionEventHandler<MouseEventData>((data)=>Console.WriteLine(data.Name)).Handle(new MouseEventData() {  Name="小黄"});
                //MouseEventHandler(new MouseEventData() { Name=this.Name});
                //EventBus.Default.Trigger(new MouseEventData() { Name=this.Name});
            }

     

    第二个问题:解决并发性的问题此时需要用到锁,所以只需要在可能产生并发的代码中加入锁即可

      //尽量保证锁中的代码少
      public static object  lockObj=new object();
      public void Register(Type dataType, Type handlerType)
            {
                lock (lockObj)
                {
                    if (mapDic.Keys.Contains(dataType))
                    {
                        if (!mapDic[dataType].Contains(handlerType))
                        {
                            mapDic[dataType].Add(handlerType);
                        }
                    }
                    else
                    {
                        mapDic[dataType] = new List<Type>() { handlerType };
                    }
                }
            }
     public void Unregister(Type eventType, Type handler)
            {
                lock (lockObj)
                {
                    if (mapDic.Keys.Contains(eventType))
                    {
                        if (mapDic[eventType].Contains(handler))
                        {
                            mapDic[eventType].Remove(handler);
                        }
                    }
                }
            }

    第四个问题:加入异步的处理方法,其实就是单独开启一个线程执行需要同步执行的代码而已

     public Task TriggerAsync<TEventData>(TEventData eventData) where TEventData : IEventData
            {
                return Task.Run(() => Trigger(eventData));
            }
    //调用一下
      static void Main(string[] args)
            {
              
                EventBus.Default.Register(typeof(MouseEventData), typeof(CatchEventHandler));
                Mouse m = new Mouse("老鼠1号");
                EventBus.Default.TriggerAsync(new MouseEventData() { Name = "xiaohuang" });
                m.Come();
                Console.Read();
            }

     第三个问题,涉及到容器,这一部分内容较多,将在接下来的随笔中学习

  • 相关阅读:
    PGsql 基本用户权限操作
    Node.js版本管理工具 nvm
    js 数字前面自动补零
    浮点数向偶数舍入的问题 Round-to-Even for Floating Point
    Linux 目录下属性查看操作
    C语言之Bit-wise Operation和Logical Operation
    (转)SqlBulkCopy批量复制数据
    (转)VS2010启动调试时老是提示正在下载公共符号
    转 SVN 在vs中的使用
    (转)关于 HTTP meta 的 IE=edge 说明
  • 原文地址:https://www.cnblogs.com/XZhao/p/8863255.html
Copyright © 2020-2023  润新知