• .NET 事件总线


    读完圣杰大佬的事件总线归纳总结的,只读了第一节,有空看一下第二节,有空梳理一下记录的笔记,下面是自己总结的步骤,后期会整理
    说是自己没有时间,其实是自己把时间都浪费掉了,这个是个坏毛病,要改,慢慢改变一下吧,
    demo如下:gitee地址
    渔夫钓鱼,需要抽离事件源,和事件处理
    一.这就是简单的发布订阅模式,第一版
    1.先定义鱼的种类
    2.定义鱼竿类
    3.在鱼竿类写委托(需要参数,鱼的种类)与事件,定义一个方法用于触发事件
    ThrowHook 下钩
    3.定义一个垂钓者类,定义一个垂钓者名称,定义一个钓鱼的数量,定义一个被观察者对象(鱼竿),定义一个方法调用鱼竿的下杆的方法,定义一个方法和鱼竿的事件绑定的方法
    4.改造鱼竿类的下杆的方法,先写上注释,开始下杆,判断当前随机数是否能除尽2如果除尽,则定义一个随机数,将鱼的类型随机一下,然后传给事件中去
    二.抽象事件源,和事件处理
    第一步,先改造事件源
    1.先处理事件源,事件源就是鱼的类型,鱼的类型太过具体了,我们需要定义一个接口将它解耦,
    事件源包含触发事件的对象和触发事件的时间,我们先定义一个接口,放这两个字段
    2.定义一个EventData,继承于IEventData,创建一个构造函数,将触发事件的事件赋值当前时间
    3.扩展一个当前钓鱼的对象,继承于EventData,为FishingData,包含两个属性,一个是鱼的种类,一个是垂钓者对象
    4.将当前的事件源全部替换为当前FishingData事件源
    把在FishingRod声明的委托参数类型改为FishingEventData类型了,即public delegate void FishingHandler(FishingEventData eventData); //声明委托;
    然后修改FishingMan的Update方法按委托定义的参数类型修改即可
    第二步,改造事件处理
    1.定义一个事件处理器的公共接口:IEventHandler
    2.定义一个泛型事件处理器接口IEventHandler,用于统一命名事件处理方法名,泛型接口的泛型类必须继承于IEventData,定义的事件处理方法名称为HandleEvent
    3.将fishingman继承于IEventHandler,将program的bug修改一下,这里我就不过多介绍了,至此完成了事件处理的抽象
    这个发布订阅模式已经可以正常使用了
    但是为了更大限度的解耦,我们需要在订阅者和发布者中间添加一个中介,想要避免订阅者同时处理多事件逻辑,我们就把事件逻辑的处理提取到订阅者外部

    第三步,如何避免在订阅者中同时处理多个事件逻辑
    自然是针对不同的事件源IEventData实现不同的IEventHandler
    这时我们就可以移除在FishingMan中实现的IEventHandler接口了。
    然后将事件注册改为fishingRod.FishingEvent += new FishiningEventHandler().HandleEvent;即可。

    第四步,统一注册事件,精简流程
    在FishingRod中写构造函数
    (1)获取当前程序集所有信息
    (2)获取当前程序集所有类型,通过遍历
    (3)判断当前类型是否实现了IEventHandler接口
    (4)如果实现了,就获取当前类型的IEventHandler泛型接口
    (5)若是不为空,则获取当前接口的参数
    (6)获取之后,用当前类型匹配是否等于FishingData
    (7)创建当前类型的实例,并且将它转换为IEventHandler
    (8)将当前类型的处理事件绑定在当前事件中

    第五步,解除依赖,事件总线登场
    1.定义一个EventBus,事件总线类
    2.准备一个字段,Default,就是当前EventBus的实例
    3.定义一个线程安全字典集合,键是Type,值是List,eventAndHandlerMapping
    4.定义一个无参构造函数,初始化字典集合,初始化MapEventToHandler方法
    5.定义一个MapEventToHandler方法,
    6.MapEventToHandler逻辑
    (1).首先获取当前程序集
    (2).获取所有类型,遍历
    (3).判断当前类型是否实现了IEventHandler
    (4).获取当前类型的泛型接口handlerInterface
    (5).判断当前泛型接口handlerInterface不为空,则获取当前接口的泛型参数eventDataType
    (6).判断当前类里的字典集合里是否包含当前eventDataType,
    (7).如果包含则将当前eventDataType里的值取出来,组成新的List
    (8).并且将当前的类型也存入这个list中,
    (9).将当前组成的这个list存入字典集合中
    (10).如果不包含eventDataType,则将当前的类型组成一个list
    (11).最后将当前的eventDataType为键,list为值存入字典集合中
    7.再写一个触发方法Trigger(TEventData eventData)
    (1).并且用泛型约束,当前泛型参数必须继承于IEventData
    (2).根据当前的泛型参数,从字典中取出它对应的值,也就是实现于泛型接口的类,组成一个list
    (3).判断当前list不为空,并且个数大于0
    (4).则遍历当前集合
    (5).用MethodInfo去接收当前方法名称是HandleEvent的方法
    (6).如果当前方法不为空,则依据当前的类型,创建一个实例,
    (7).通过当前方法.Invoke直接调用方法,并且传入参数,就是我们的入参

  • 相关阅读:
    可变参数宏
    指针用作传出参数时,需要二级指针
    ubuntu下配置tftp服务以及开发板中通过tftp下载文件
    calloc()函数和malloc()函数
    android 之反编译
    snprintf()函数使用方法
    android 之对话框的使用
    ubuntu su 密码
    android 发短信 调到联系人
    ubuntu 11.10 android ndk awk安装错误修改记
  • 原文地址:https://www.cnblogs.com/humblexwang/p/16221770.html
Copyright © 2020-2023  润新知