在c#中代理和事件是个难点,也是个重点,但是当你真正的搞懂它之后就会觉得还是很有意思的。

今天就记录下我自己对代理和事件的理解,方便日后只用。我也是看了网上的两篇文章使我受益匪浅,在这里先刚写这两篇文章的作者,并附上链接:http://www.cnblogs.com/michaelxu/archive/2008/04/02/1134217.html

http://www.cnblogs.com/jimmyzhang/archive/2007/09/23/903360.html


   在c#中delegate很好理解,可以把代理理解为函数指针,在我的这篇文章中主要讨论的是代理和事件之间是如何建立联系的,想要仔细了解代理的可以去上面两篇文章中看看。下面这要通过两个实例来了解代理和事件之间的关系,理论总是抽象的,我们要来点具体的。下面就开始吧。

   第一个实例是实现一个按键的触发机制,当你触发一个键盘按键的时候将按键信息和发送信息的对象显示出来。首先实现一个KeyEventArgs类


//保存发送的信息的类;
    class KeyEventArgs:EventArgs
    {
        private char keyCode;
        public KeyEventArgs(char key):base()
        {
            this.keyCode = key;
        }
        public char KeyCode
        {
            get
            {
                return keyCode;
            }
        }
    }

然后实现一个发送按键消息的类keyInputMonitor


//消息的触发者,当有事件发生时发送消息
    class keyInputMonitor
    {
//定义一个代理
        public delegate void KeyDownHandler(object sender,KeyEventArgs e);
//事件的定义
        public event KeyDownHandler KeyDown;
//这个方法是一直在运行,当按键不是‘X’的时候我们将按键信息发送给事件的接受者,否则就退出程序
        public void Run()
        {
            bool finish = false;
            do
            {
                Console.WriteLine("Input a char:");
                string s = Console.ReadLine();
                char key = (s == "")?' ':Char.ToUpper(s[0]);
                switch (key)
                {
                    case 'X':
                        finish = true;
                        break;
                    default:
                        if(KeyDown != null){
                            KeyEventArgs e = new KeyEventArgs(key);
                            KeyDown(this,e);
                        }
                        break;
                }
            } while (!finish);
        }
    }

下面再添加一个事件的接受类EventReceiver

//消息的接受者
    class EventReceiver{
//在EventReceiver类中我们将事件的处理函数OnKeyDown添加上去
        public EventReceiver(keyInputMonitor monitor){
            monitor.KeyDown += new keyInputMonitor.KeyDownHandler(OnKeyDown);
        }
//事件的处理函数,当事件发生时我们输出一些信息
        public void  OnKeyDown(object sender,KeyEventArgs e){
            Console.WriteLine("sender:"+sender+"\ne:" + e.KeyCode);
        }
    }

最后在主程序中调用

class Program
   {
       static void Main(string[] args)
       {
           keyInputMonitor kim =  new keyInputMonitor();
           EventReceiver er = new EventReceiver(kim);
           kim.Run();
       }
   }

ok了,当你在键盘上按下按键的时候,接受类会将接受到的信息显示到屏幕的。


   第二个例子是实现一个水开的事件,首先有个热水器在烧水,还有一个显示器,当水温到达90以上的时候我们显示水温,并且有个警报器要发出警报,是不是有点意思啊。好吧,下面就继续吧。

首先是一个保存温度的类:

class TemperatureEventArgs : EventArgs{
        private int temperature;
        public TemperatureEventArgs(int tem){
            this.temperature = tem;
        }
        public int Temperature{
            get{
                return temperature;
            }
                                                               
        }
    }

然后是一个热水器的类:

class Heater
   {
       //代理
       public delegate void TemperatureHandler(object sender,TemperatureEventArgs e);
     //事件
       public event TemperatureHandler TemperatureDown;
      //热水器烧水的动作
       public void  Run(){
           for (int i =0 ;i<100;i++)
           {
               if(i > 90){
                   if(TemperatureDown != null){
                       TemperatureEventArgs e = new TemperatureEventArgs(i);
                       TemperatureDown(this,e);
                   }
               }
           }
       }
   }

再写个警报器类:

class Alarm
    {
        public Alarm(Heater h)
        {
            h.TemperatureDown += new Heater.TemperatureHandler(OnAlarm);
        }
        public void OnAlarm( object sender,TemperatureEventArgs e)
        {
            Console.WriteLine("滴滴滴。。。" + "\n水开了。。。" );//+ "\n sender:"+sender + "\n eventArgs:" + e.Temperature);
        }
    }

还有一个显示器的类:

class Display
   {
       public Display(Heater h)
       {
           h.TemperatureDown += new Heater.TemperatureHandler(OnDisPlay);
       }
       public void OnDisPlay(object sender,TemperatureEventArgs e)
       {
           Console.WriteLine("现在的温度是:" + e.Temperature);
       }
   }

最后是我们的主程序的调用:

class Program
    {
        static void Main(string[] args)
        {
            Heater h = new Heater();
            Alarm alarm = new Alarm(h);
            Display display = new Display(h);
            h.Run();
            Console.ReadLine();
        }
    }