• 事件EventHander使用原理


    事件的整个过程牵涉到发布程序、侦听器和事件的相关信息对象,要想一个对象具有事件处理功能,

    则需要在此对象中声明public event EventHandler<T> eventObject 类似这样的语句,其中T为发布程

    序和侦听器之间交流的参数类型,即他们之间传递信息的“数据包”,T还必须有一个约束,即它必须派

    生自基类EventArgs,通过此数据包来来知道事件触发后,侦听器要做一些怎样的具体的操作。例如:

    一个窗口,具有事件处理功能,则当鼠标在窗口中的某个位置点击时,触发事件,T则是包含鼠标在窗

    口中位置的具体信息的对象,例:

    class Point     //鼠标位置对象

    {

         public int xPosition;        //鼠标的x轴坐标

         public int yPosition;       //鼠标的y轴坐标

    }

    事件处理程序接收到这个对象后根据这个对象里面包含的具体事件信息做出相应的反应。下面列出一段代码慢慢体会

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    namespace Example
    {
        public class CarInfoEventArgs : EventArgs      //用来作为事件发送者和事件处理者之间的参数传递
        {
            public string Car { get; private set; }
            public CarInfoEventArgs(string car)
            {
                this.Car = car;
            }
        }
        public class CarDealer           //事件源
        {
            public event EventHandler<CarInfoEventArgs> NewCarInfo;//代表此类能够处理事件,其中事件的相关信息类型为CarInfoEventArgs
            public void NewCar(string car)
            {
                Console.WriteLine("CarDealer,new car{0}", car);
                if (NewCarInfo != null)    //判断事件触发器是否有事件处理程序注册
                {
                    //第一个参数是一个对象,包含事件的发送者,第二个参数提供了事件的相关信息
                    NewCarInfo(this, new CarInfoEventArgs(car));
                }
            }
        }
        public class Consumer      //事件处理程序
        {
            private string name;
            public Consumer(string name)
            {
                this.name = name;
            }
            public void NewCarIsHere(object sender, CarInfoEventArgs e)
            {
                Console.WriteLine("{0};car{1} is new", name, e.Car);
            }
        }
        class Program
        {
            static void Main()
            {
                var dealer = new CarDealer();
                var michael = new Consumer("Michael");
                dealer.NewCarInfo += michael.NewCarIsHere;   //将事件处理程序注册到事件触发器
                dealer.NewCar("Mercedes");  //触发事件
                var nick = new Consumer("Nick");
                dealer.NewCarInfo += nick.NewCarIsHere;
                dealer.NewCar("Ferrari");
                dealer.NewCarInfo -= michael.NewCarIsHere;
                dealer.NewCar("Toyota");
            }
        }
    }

    通过以上事件原理实现的事件程序,存在垃圾回收问题,例如,若果侦听器不再直接引用,发布程序就仍有一个引用,

    垃圾回收器不能清空侦听器占用的内存,因为发布程序仍保有一个引用,会针对侦听器触发事件。

    这种强连接可以通过弱事件模式来解决,即使用WeakEventManager作为发布程序和侦听器之间的中介。对以上程序做

    如下更改:发布程序和“数据包”保持不变,侦听器实现IWeakEventListener接口,同时增加一个弱事件管理器,它管理发

    布程序和侦听器之间的连接程序如下,慢慢体会:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    namespace Example
    {
        public class CarInfoEventArgs : EventArgs       //数据包
        {
            public string Car { get; private set; }
            public CarInfoEventArgs(string car)
            {
                this.Car = car;
            }
        }
        public class CarDealer             //发布程序
        {
            public event EventHandler<CarInfoEventArgs> NewCarInfo;
            public void NewCar(string car)
            {
                Console.WriteLine("CarDealer,new car{0}", car);
                if (NewCarInfo != null)
                {
                    NewCarInfo(this, new CarInfoEventArgs(car));
                }
            }
        }
        public class Consumer : IWeakEventListener      //侦听器
        {
            private string name;
            public Consumer(string name)
            {
                this.name = name;
            }
            public void NewCarIsHere(object sender, CarInfoEventArgs e)
            {
                Console.WriteLine("{0}:car{1} is new", name, e.Car);
            }
            bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e)//实现接口中的方法
            {
                NewCarIsHere(sender, e as CarInfoEventArgs);
                return true;
            }
        }
        public class WeakCarInfoEventManager : WeakEventManager    //弱事件管理器
        {
            public static WeakCarInfoEventManager CurrentManager
            {
                get
                {
                    WeakCarInfoEventManager manager = GetCurrentManager(typeof(WeakCarInfoEventManager)) as WeakCarInfoEventManager;
                    if (manager == null)
                    {
                        manager = new WeakCarInfoEventManager();
                        SetCurrentManager(typeof(WeakCarInfoEventManager), manager);
                    }
                    return manager;
                }
            }
            public static void AddListener(object source, IWeakEventListener listener)  //添加侦听器
            {
                CurrentManager.ProtectedAddListener(source, listener);   
            }
            public static void RemoveListener(object source, IWeakEventListener listener)//删除侦听器
            {
                CurrentManager.ProtectedRemoveListener(source, listener);
            }
            //重写基类中的方法,添加第一个侦听器时调用
            protected override void StartListening(object source)  
            {
                (source as CarDealer).NewCarInfo += CarDealer_NewCarInfo;
            }
            //重写基类中的方法,删除最后一个侦听器时调用
            protected override void StopListening(object source)  
            {
                (source as CarDealer).NewCarInfo -= CarDealer_NewCarInfo;
            }
            void CarDealer_NewCarInfo(object sender, CarInfoEventArgs e)
            {
                //把事件传递给侦听器,此方法在侦听器中调用IWeakEventListener接口中的ReceiveWeakEvent()方法
                DeliverEvent(sender, e);  
            }
        }
        class Program
        {
            static void Main()
            {
                var dealer = new CarDealer();
                var michael = new Consumer("Michael");
                WeakCarInfoEventManager.AddListener(dealer, michael);
                dealer.NewCar("Mercedes");
                var nick = new Consumer("Nick");
                WeakCarInfoEventManager.AddListener(dealer, nick);
                dealer.NewCar("Ferrari");
                WeakCarInfoEventManager.RemoveListener(dealer, michael);
                dealer.NewCar("Toyota");
            }
        }
    }


  • 相关阅读:
    eclipse、idea安装lombok插件
    ContextLoaderListener加载过程
    web.xml 文件中一般包括 servlet, spring, filter, listenr的配置的加载顺序
    springboot
    root cause org.apache.ibatis.ognl.OgnlException: source is null for getProperty(null, "XXX")
    Java MyBatis 插入数据库返回主键
    Mybatis异常There is no getter for property named 'XXX' in 'class com.xxx.xxx.UserAccountDTO
    web项目,ftl文件中的路径引入问题
    mybatis No enum const class org.apache.ibatis.type.JdbcType.Integer
    Restful、Jersey和JAX-RS
  • 原文地址:https://www.cnblogs.com/zztong/p/6695172.html
Copyright © 2020-2023  润新知