• 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()[0];
                        if (arg.Equals(typeof(MouseEventData)))
                        {
                            var handler = Activator.CreateInstance(type) as IEventHandler<MouseEventData>;
                            this.selfEventHandler += handler.Handle;
                        }
                    }
                }
            }
            public void Comming(string name )
            {
                Console.WriteLine("老鼠说:
    ");
    
                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();
            }
          
        }

    运行一下:

    今天那就先到这里了。



     
  • 相关阅读:
    委托和事件
    Entity Framework应用:导航属性
    Entity Framework应用:根据实体的EntityState状态实现增删改查
    Entity Framework应用:使用EF的DataBase First模式实现数据库的增删改查
    Entity Framework应用:EntityFramework DataBase First模式
    dapper支持操作函数和事物
    单元测试
    IOC容器:Unity
    MVC教程九:异常过滤器
    MVC教程八:缓存过滤器
  • 原文地址:https://www.cnblogs.com/XZhao/p/8712196.html
Copyright © 2020-2023  润新知