ABP之事件总线(2)
在上一篇文章中,我们复习了一下事件的经典的发布订阅模式,同时对是事件源和时间处理逻辑进行抽象统一,用起来也没有问题。但是还是有很多的问题,比如说我们Handle方法其实是违背了单一性的原则的,里面混杂了各个EventData的处理逻辑,这个方法将会越来越大,越来越慢,看着越来越难受。好,那么先解决今天的第一个问题。既然我们前面为了单一化原则,分别定义了不同的xxEventData,那么我们可以同样的定义不同的xxEventHandler.
创建不同的Handler
public class FishingEventHandler : IEventHandler<FishEventData>
{
public void Handle(FishEventData eventData)
{
Console.WriteLine("小猫说:");
Console.WriteLine("我吃了{0}斤鱼",eventData.FishWeight);
}
}
public class MouseEventHandler : IEventHandler<MouseEventData>
{
public void Handle(MouseEventData eventData)
{
Console.WriteLine("小猫说:");
Console.WriteLine("我抓到了{0}老鼠", eventData.MouseName);
}
}
实现猫捉老鼠
static void Main(string[] args)
{ Cat c1 = new Cat();
Mouse m1 = new Mouse("1号老鼠"); //订阅事件
// m1.selfEventHandler += c1.Handle;
m1.selfEventHandler += new MouseEventHandler().Handle;
//触发事件
m1.Comming(m1.Name); Console.ReadLine();
}
到了这里,可能会感到疑问了,我们做了这么多的工作,又回到了最初的起点???事件的处理逻辑还是得重新写。。。。但是!!!!有没有发现一个问题,我们把事件整个的脱离出来了,不再依赖于猫(订阅者),而是直接订阅事件,关键是还有一个关键的发现,那就是我们统一了事件的处理逻辑方法的名称,统一为Handle。这样大大方便了我们的开发,以后我们编写事件的时候,只需要编写对应的xxxEventData和xxxEventHandler就可以了,是不是很方便!是不是有一种解除耦合的感觉!

上面的这行代码是我们手动注册我们的事件处理逻辑,现在问题来了刚才我们写的是猫捉老鼠的处理逻辑,现在来了,狗捉老鼠,牛捉老鼠,大象捉老鼠。。。。此时创建了DogMouseEventHandler:IEventHandler<MouseEventData>、NiuMouseEventHandler:IEventHandler<MouseEventData>、ElephantMouseEventHandler:IEventHandler<MouseEventData>
m1.selfEventHandler += new DogMouseEventHandler().Handle;
m1.selfEventHandler += new NiuMouseEventHandler().Handle;
m1.selfEventHandler += new ElephantMouseEventHandler().Handle;
如果我们再动态的添加很多,此时我们的代码还是需要修改。。。。。那么如何解决这个问题呢?也就是如何代替显示的注册,而是直接自动的动态的注册。那就只能从程序集入手了。。。用到的技术也就是我们常说的反射。 所以我们重新修改Mouse类
public class Mouse
{ //声明事件委托
public event MouserEventHandler selfEventHandler;
public Mouse(string name)
{
this.Name = name;
var asm = Assembly.GetExecutingAssembly();
foreach (var type in asm.GetTypes())
{
//判断当前的类型是否实现了IEventHandler接口
if (typeof(IEventHandler).IsAssignableFrom(type))
{
//获取该type实现了泛型的IEventhandler接口
var handlerInterface = type.GetInterface("IEventHandler`1");
if (handlerInterface == null)
continue;
var arg = handlerInterface.GetGenericArguments()[];
if (arg.Equals(typeof(MouseEventData)))
{
var handler = Activator.CreateInstance(type) as IEventHandler<MouseEventData>;
this.selfEventHandler += handler.Handle;
}
}
}
}
public void Comming(string name )
{
Console.WriteLine("老鼠说:\n"); Console.WriteLine("我的名字是{0},I am Comming!", name);
//触发事件
selfEventHandler(new MouseEventData() { MouseName = name});
}
public string Name { get; set; } }
上面的代码中我们将Mouse类的构造函数进行重写,在构造函数中使用反射的方式实现事件逻辑的注册。

上面标注的地方由两个需要注意的地方:1.必须是IEventHandler`1,而不是IEventHandler,如果使用IEventHander,那么IEventHandler<TEventData>也将会被获取到,此时获取参数是没有的,所以会出现索引超出的错误
2.IEventHandler`1,这是固定的获取泛型接口的方法

此时我们的猫捉老鼠
class Program
{
static void Main(string[] args)
{ Cat c1 = new Cat();
Mouse m1 = new Mouse("1号老鼠"); //订阅事件
// m1.selfEventHandler += c1.Handle;
// m1.selfEventHandler += new MouseEventHandler().Handle;
//触发事件
m1.Comming(m1.Name); Console.ReadLine();
} }
运行一下:

今天那就先到这里了。
ABP之事件总线(2)的更多相关文章
- ABP之事件总线(5)
前面已经对Castle Windsor的基本使用进行了学习,有了这个基础,接下来我们将把我们的事件总线再次向ABP中定义的事件总线靠近.从源码中可以知道在ABP中定义了Dictionary,存放三种类 ...
- ABP之事件总线(4)
在上一篇的随笔中,我们已经初步完成了EventBus,但是EventBus中还有诸多的问题存在,那么到底有什么问题呢,接下来我们需要看一看ABP中的源码是如何定义EventBus的. 1.第一个点 在 ...
- ABP之事件总线(3)
承接上一篇时间总线的学习,在上一篇中我们实现了取消显式注册事件的方式,采用使用反射的方式.这样的好处可以解除Publisher和Scriber的显式依赖,但是问题又来了,因为我们只有Publisher ...
- ABP之事件总线(1)
什么是事件总线呢?官方的文档说,它是一个单例对象,由其他的类共同拥有,可以用来触发和处理事件.这个东西确实比较陌生,为什么要使用事件总线,或者说事件总线的优势是什么???首先我们可以明确的是,事件总线 ...
- ABP的事件总线和领域事件(EventBus & Domain Events)
http://www.aspnetboilerplate.com/Pages/Documents/EventBus-Domain-Events EventBus EventBus是个单例,获得Even ...
- [Abp 源码分析]九、事件总线
0.简介 事件总线就是订阅/发布模式的一种实现,本质上事件总线的存在是为了降低耦合而存在的. 从上图可以看到事件由发布者发布到事件总线处理器当中,然后经由事件总线处理器调用订阅者的处理方法,而发布者和 ...
- ABP理论学习之事件总线和领域事件
返回总目录 本篇目录 事件总线 定义事件 触发事件 处理事件 句柄注册 取消注册 在C#中,我们可以在一个类中定义自己的事件,而其他的类可以注册该事件,当某些事情发生时,可以通知到该类.这对于桌面应用 ...
- ABP官方文档翻译 3.7 领域事件(事件总线)
领域事件(事件总线) 事件总线 注入IEventBus 获取默认实例 定义事件 预定义事件 处理异常 实体更改 触发事件 处理事件 处理基础事件 处理者异常 处理多个事件 注册处理者 自动 手动 取消 ...
- ABP EventBus(事件总线)
事件总线就是订阅/发布模式的一种实现 事件总线就是为了降低耦合 1.比如在winform中 到处都是事件 触发事件的对象 sender 事件的数据 e 事件的处理逻辑 方法体 通过E ...
随机推荐
- 【ZH奶酪】如何用textgenrnn处理中文
如何用textgenrnn处理中文 1. 什么是textgenrnn? textgenrnn是建立在Keras和TensorFlow之上的,可用于生成字级别和词级别文本.网络体系结构使用注意力加权来加 ...
- Ubuntu16.04上使用Anaconda3的Python3.6的pip安装UWSGI报错解决办法
具体报错信息: lto1: fatal error: bytecode stream generated with LTO version 6.0 instead of the expected 4. ...
- 【LeetCode】238. Product of Array Except Self
Product of Array Except Self Given an array of n integers where n > 1, nums, return an array outp ...
- More than the maximum number of request parameters
前些时间,我们的的一个管理系统出现了点问题,原本运行的好好的功能,业务方突然讲不行了,那个应用已经运行了好多年了,并且对应的代码最近谁也没改动过,好奇怪的问题,为了解决此问题,我们查看了日志,发现请求 ...
- Eureka微服务ID
Instance ID用于唯一标识注册到Eureka Server上的微服务实例.我们可在Eureka Server的首页直观地看到各个微服务的Instance ID.例如,图11-1中的itmuch ...
- Go 程序的性能调试问题
英文原文:Debugging performance issues in Go programs 假设你手上有个Go语言编写的程序,你打算提升它的性能.目前有一些工具可以为此提供帮助.这些工具能帮你发 ...
- SQL SERVER 行列转换(动态)
行转列测试数据: --测试数据 if not object_id(N'Tempdb..#T') is null drop table #T Go Create table #T([Name] nvar ...
- 3D打印技术之切片引擎(5)
[此系列文章基于熔融沉积( fused depostion modeling, FDM )成形工艺] 从这一篇文章開始,就開始说填充.在3D打印切片技术中,填充算法是最核心的部分.3D打印技术的经常使 ...
- 【spark 深入学习 06】RDD编程之旅基础篇02-Spaek shell
--------------------- 本节内容: · Spark转换 RDD操作实例 · Spark行动 RDD操作实例 · 参考资料 --------------------- 关于学习编程方 ...
- ①Android NuPlayer播放框架
[时间:2016-09] [状态:Open] [关键词:android,nuplayer,开源播放器,播放框架,nuplayerdriver] 0 NuPlayer简介 Android2.3时引入流媒 ...