在上一篇文章中,我们复习了一下事件的经典的发布订阅模式,同时对是事件源和时间处理逻辑进行抽象统一,用起来也没有问题。但是还是有很多的问题,比如说我们Handle方法其实是违背了单一性的原则的,里面混杂了各个EventData的处理逻辑,这个方法将会越来越大,越来越慢,看着越来越难受。好,那么先解决今天的第一个问题。既然我们前面为了单一化原则,分别定义了不同的xxEventData,那么我们可以同样的定义不同的xxEventHandler.

创建不同的Handler

  1. public class FishingEventHandler : IEventHandler<FishEventData>
  2. {
  3. public void Handle(FishEventData eventData)
  4. {
  5. Console.WriteLine("小猫说:");
  6. Console.WriteLine("我吃了{0}斤鱼",eventData.FishWeight);
  7. }
  8. }
  9. public class MouseEventHandler : IEventHandler<MouseEventData>
  10. {
  11. public void Handle(MouseEventData eventData)
  12. {
  13. Console.WriteLine("小猫说:");
  14. Console.WriteLine("我抓到了{0}老鼠", eventData.MouseName);
  15. }
  16. }

实现猫捉老鼠

  1. static void Main(string[] args)
  2. {
  3.  
  4. Cat c1 = new Cat();
  5. Mouse m1 = new Mouse("1号老鼠");
  6.  
  7. //订阅事件
  8. // m1.selfEventHandler += c1.Handle;
  9. m1.selfEventHandler += new MouseEventHandler().Handle;
  10. //触发事件
  11. m1.Comming(m1.Name);
  12.  
  13. Console.ReadLine();
  14. }

到了这里,可能会感到疑问了,我们做了这么多的工作,又回到了最初的起点???事件的处理逻辑还是得重新写。。。。但是!!!!有没有发现一个问题,我们把事件整个的脱离出来了,不再依赖于猫(订阅者),而是直接订阅事件,关键是还有一个关键的发现,那就是我们统一了事件的处理逻辑方法的名称,统一为Handle。这样大大方便了我们的开发,以后我们编写事件的时候,只需要编写对应的xxxEventData和xxxEventHandler就可以了,是不是很方便!是不是有一种解除耦合的感觉!

上面的这行代码是我们手动注册我们的事件处理逻辑,现在问题来了刚才我们写的是猫捉老鼠的处理逻辑,现在来了,狗捉老鼠,牛捉老鼠,大象捉老鼠。。。。此时创建了DogMouseEventHandler:IEventHandler<MouseEventData>、NiuMouseEventHandler:IEventHandler<MouseEventData>、ElephantMouseEventHandler:IEventHandler<MouseEventData>

  1. m1.selfEventHandler += new DogMouseEventHandler().Handle;
  1. m1.selfEventHandler += new NiuMouseEventHandler().Handle;
  1. m1.selfEventHandler += new ElephantMouseEventHandler().Handle;
    如果我们再动态的添加很多,此时我们的代码还是需要修改。。。。。那么如何解决这个问题呢?也就是如何代替显示的注册,而是直接自动的动态的注册。那就只能从程序集入手了。。。用到的技术也就是我们常说的反射。
  2.  
  3. 所以我们重新修改Mouse
  1. public class Mouse
  2. {
  3.  
  4. //声明事件委托
  5. public event MouserEventHandler selfEventHandler;
  6. public Mouse(string name)
  7. {
  8. this.Name = name;
  9. var asm = Assembly.GetExecutingAssembly();
  10. foreach (var type in asm.GetTypes())
  11. {
  12. //判断当前的类型是否实现了IEventHandler接口
  13. if (typeof(IEventHandler).IsAssignableFrom(type))
  14. {
  15. //获取该type实现了泛型的IEventhandler接口
  16. var handlerInterface = type.GetInterface("IEventHandler`1");
  17. if (handlerInterface == null)
  18. continue;
  19. var arg = handlerInterface.GetGenericArguments()[];
  20. if (arg.Equals(typeof(MouseEventData)))
  21. {
  22. var handler = Activator.CreateInstance(type) as IEventHandler<MouseEventData>;
  23. this.selfEventHandler += handler.Handle;
  24. }
  25. }
  26. }
  27. }
  28. public void Comming(string name )
  29. {
  30. Console.WriteLine("老鼠说:\n");
  31.  
  32. Console.WriteLine("我的名字是{0},I am Comming!", name);
  33. //触发事件
  34. selfEventHandler(new MouseEventData() { MouseName = name});
  35. }
  36. public string Name { get; set; }
  37.  
  38. }
  1.  

上面的代码中我们将Mouse类的构造函数进行重写,在构造函数中使用反射的方式实现事件逻辑的注册。

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

2.IEventHandler`1,这是固定的获取泛型接口的方法

此时我们的猫捉老鼠

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5.  
  6. Cat c1 = new Cat();
  7. Mouse m1 = new Mouse("1号老鼠");
  8.  
  9. //订阅事件
  10. // m1.selfEventHandler += c1.Handle;
  11. // m1.selfEventHandler += new MouseEventHandler().Handle;
  12. //触发事件
  13. m1.Comming(m1.Name);
  14.  
  15. Console.ReadLine();
  16. }
  17.  
  18. }

运行一下:

今天那就先到这里了。

  1.  
  1.  

ABP之事件总线(2)的更多相关文章

  1. ABP之事件总线(5)

    前面已经对Castle Windsor的基本使用进行了学习,有了这个基础,接下来我们将把我们的事件总线再次向ABP中定义的事件总线靠近.从源码中可以知道在ABP中定义了Dictionary,存放三种类 ...

  2. ABP之事件总线(4)

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

  3. ABP之事件总线(3)

    承接上一篇时间总线的学习,在上一篇中我们实现了取消显式注册事件的方式,采用使用反射的方式.这样的好处可以解除Publisher和Scriber的显式依赖,但是问题又来了,因为我们只有Publisher ...

  4. ABP之事件总线(1)

    什么是事件总线呢?官方的文档说,它是一个单例对象,由其他的类共同拥有,可以用来触发和处理事件.这个东西确实比较陌生,为什么要使用事件总线,或者说事件总线的优势是什么???首先我们可以明确的是,事件总线 ...

  5. ABP的事件总线和领域事件(EventBus & Domain Events)

    http://www.aspnetboilerplate.com/Pages/Documents/EventBus-Domain-Events EventBus EventBus是个单例,获得Even ...

  6. [Abp 源码分析]九、事件总线

    0.简介 事件总线就是订阅/发布模式的一种实现,本质上事件总线的存在是为了降低耦合而存在的. 从上图可以看到事件由发布者发布到事件总线处理器当中,然后经由事件总线处理器调用订阅者的处理方法,而发布者和 ...

  7. ABP理论学习之事件总线和领域事件

    返回总目录 本篇目录 事件总线 定义事件 触发事件 处理事件 句柄注册 取消注册 在C#中,我们可以在一个类中定义自己的事件,而其他的类可以注册该事件,当某些事情发生时,可以通知到该类.这对于桌面应用 ...

  8. ABP官方文档翻译 3.7 领域事件(事件总线)

    领域事件(事件总线) 事件总线 注入IEventBus 获取默认实例 定义事件 预定义事件 处理异常 实体更改 触发事件 处理事件 处理基础事件 处理者异常 处理多个事件 注册处理者 自动 手动 取消 ...

  9. ABP EventBus(事件总线)

    事件总线就是订阅/发布模式的一种实现    事件总线就是为了降低耦合 1.比如在winform中  到处都是事件 触发事件的对象  sender 事件的数据    e 事件的处理逻辑  方法体 通过E ...

随机推荐

  1. Android ViewFlipper增添ScrollView后不能滑动了

    Android ViewFlipper添加ScrollView后不能滑动了在Activity中添加ScrollView实现滚动activity的效果后,activity的滑动效果却无法生效了,原因是因 ...

  2. SDUT 3002-素数间隙(素数筛+暴力)

    素数间隙 Time Limit: 1000ms   Memory limit: 262144K  有疑问?点这里^_^ 题目描写叙述 Neko猫是一个非常喜欢玩数字游戏的会说话的肥猫,常常会想到非常多 ...

  3. [Python设计模式] 第11章 迪米特法则——最少知识原则

    github地址:https://github.com/cheesezh/python_design_patterns 迪米特法则 迪米特法则(LoD),也叫最少知识原则,如果两个类不必彼此直接通信, ...

  4. from String value ('{}'); no single-String constructor/factory

    需要为类增加一个接受String的构造函数: 例如: public class B { private String name; public B(String b) { } public Strin ...

  5. WCF兼容WebAPI输出Json格式数据,从此WCF一举两得

    问题起源: 很多时候为了业务层调用(后台代码),一些公共服务就独立成了WCF,使用起来非常方便,添加服务引用,然后简单配置就可以调用了. 如果这个时候Web站点页面需要调用怎么办呢? 复杂的XML , ...

  6. Struct2 (一)

    STRUCT2 权威指南(1) MVC思想将一个应用分成三个基本部分:Model(模型).View(视图)和Controller(控制器),这三个部分以最少的耦合协同工作,从而提高应用的可扩展性及可维 ...

  7. [转]linux(ubuntu)上运行网易popo

    popo没有linux版,连web版和android版都没有,这个实在是不方便.搞了很久,终于搞定了ubuntu上运行popo,暂时还没出现什么问题. 首先要安装PlayOnLinux,直接安装win ...

  8. Spring开发工具Spring Tools Suite(STS)

    The Spring Tool Suite is an Eclipse-based development environment that is customized for developing ...

  9. [BigData - Hadoop - YARN] YARN:下一代 Hadoop 计算平台

    Apache Hadoop 是最流行的大数据处理工具之一.它多年来被许多公司成功部署在生产中.尽管 Hadoop 被视为可靠的.可扩展的.富有成本效益的解决方案,但大型开发人员社区仍在不断改进它.最终 ...

  10. [转](OS 10038)在一个非套接字上尝试了一个操作 的解决办法

    原文: http://blog.csdn.net/zooop/article/details/47170885 可能是安装了某些程序修改了Winsock,使用netsh winsock reset 命 ...