关于委托、事件、处理事件的方法以及.NET 续一个实例

上次写了一篇关于事件处理的理论性的文章,这一次通过MSDN的一个例子说得更明白一点。

这个例子是MSDN上一个闹钟的例子,已经有了英文的注释,但是我根据我的理解再解释一番,下面我边粘源代码边说明。

综述:下面的示例程序阐释如何在一个类中引发一个事件,然后在另一个类中处理该事件。AlarmClock 类定义公共事件 Alarm,并提供引发该事件的方法。AlarmEventArgs 类派生自 EventArgs,并定义 Alarm 事件特定的数据。WakeMeUp 类定义处理 Alarm 事件的 AlarmRang 方法。AlarmDriver 类一起使用类,将使用 WakeMeUp 的 AlarmRang 方法设置为处理 AlarmClock 的 Alarm 事件。

代码看起来有点费劲,但是我尽量将它分成一块一块的,看着舒服点。

 

namespace EventSample

   using System;
   using System.ComponentModel;
   

   //定义一个EventArgs类名字叫AlarmEventArgs,为的就是可以传递自己想要的参数供alarm事件用。上一篇里说到.NET里已经对于各个事件定义了相对应的类,一般也不需要我们自己定义。这里为了说明原理,或者有时我们需要传递一些我们自己想要传递的参数,需要自己定义这样的类,说白了,就是马克思主义中国化
   public class AlarmEventArgs : EventArgs
   { 
      private readonly bool snoozePressed ;
      private readonly int nrings;
     
      //构建函数,初始化两个成员
      public AlarmEventArgs(bool snoozePressed, int nrings)
      {
         this.snoozePressed = snoozePressed;
         this.nrings = nrings;
      }
      
//这个就是返回成员属性值,只读的

//响几次
      public int NumRings
      {    
         get { return nrings;}     
      }
      
      //要不要响
      public bool SnoozePressed
      {
         get {return snoozePressed;}
      }
      
      //闹铃触发的时候显示的信息
      public string AlarmText
      {
         get
         {
            if (snoozePressed)
            {
               return ("Wake Up!!! Snooze time is over.");
            }
            else
            {
               return ("Wake Up!");
            }
         }
      } 
   }
  
   // 定义处理alarm事件的委托

   public delegate void AlarmEventHandler(object sender, AlarmEventArgs e);
  
   // 触发alarm事件的泪
   //

   public class AlarmClock
   { 
      private bool snoozePressed = false;
      private int nrings = 0;
      private bool stop = false;
      

      // 是否应该停止
      //
      public bool Stop
      {
         get {return stop;}
         set {stop = value;}
      }
      
      //当alarm事件触发的时候打盹按钮是否被按下,默认是没有
      public bool SnoozePressed
      {
         get {return snoozePressed;}
         set {snoozePressed = value;}
      }
      // 这里定义alarm事件,用的是AlarmEventHandler 委托.
      //
      public event  AlarmEventHandler Alarm;


      //OnAlarm方法是引发alarm事件的受保护的方法,只能由该类的实例引发
      protected virtual void OnAlarm(AlarmEventArgs e)
      {
         if (Alarm != null)
         {
            // 通过委托触发事件,这里就是关键.

            //事件也是通过方法触发的。在.net里面,这个过程比如单击按钮这类的事件的触发都是.net里面设计好的,也就是说这个函数通常是用不到也看不到的,所以里面的参数也是系统给初始化的,无须开发人员干涉。平常用到的都是直接用那个e。
            Alarm(this, e);
         }
      }
      
      //这个闹钟没有用户界面,为了模拟这个机制,在程序里面有一个循环,如果打盹的按钮没被按下,这个循环不断地每200毫秒去触发一次事件(也就是说,这个程序一执行,就等于人用的这个闹钟到时间了,要响铃了)。如果打盹的按钮被按下,每隔1秒触发一次事件
      public void Start()
      {
         for (;;)   
         {
            nrings++;     
            if (stop)
            {
               break;
            }
           
            else if (snoozePressed)
            {
               System.Threading.Thread.Sleep(1000);
               {
                  AlarmEventArgs e = new AlarmEventArgs(snoozePressed,
                     nrings);
                  OnAlarm(e);
               }
            }
            else
            {
               System.Threading.Thread.Sleep(300);
               AlarmEventArgs e = new AlarmEventArgs(snoozePressed,
                  nrings);
                (e);
            }          
         }
      }
   }
   
   //这个WakeMeUp类其实就是为了定义一个处理alarm事件的方法

   public class WakeMeUp
   {
     
      public void AlarmRang(object sender, AlarmEventArgs e)
      {
         //这里这个AlarmText属性就是自定义的,EventArgs里面是没有这个属性的,这也体现了自定义的好处
         Console.WriteLine(e.AlarmText +"/n");
        
         if (!(e.SnoozePressed))
         {
            if (e.NumRings % 10 == 0)
            {
               Console.WriteLine(" Let alarm ring? Enter Y");
               Console.WriteLine(" Press Snooze? Enter N");
               Console.WriteLine(" Stop Alarm? Enter Q");
               String input = Console.ReadLine();
              
               if (input.Equals("Y") ||input.Equals("y")) return;
              
               else if (input.Equals("N") || input.Equals("n"))
               {
                  ((AlarmClock)sender).SnoozePressed = true;
                  return;
               }
               else
               {
                  ((AlarmClock)sender).Stop = true;
                  return;
               }
            }
         }
         else
         {
            Console.WriteLine(" Let alarm ring? Enter Y");
            Console.WriteLine(" Stop Alarm? Enter Q");
            String input = Console.ReadLine();
            if (input.Equals("Y") || input.Equals("y")) return;
            else
            {
               ((AlarmClock)sender).Stop = true;
               return;
            }
         }
      }
   }
   
   //这里就是启用这个闹钟了
   public class AlarmDriver
   { 
      public static void Main (string[] args)
      { 
         // Instantiates the event receiver.
         WakeMeUp w= new WakeMeUp();
                 
         // Instantiates the event source.
         AlarmClock clock = new AlarmClock();

         // Wires the AlarmRang method to the Alarm event.
         clock.Alarm += new AlarmEventHandler(w.AlarmRang);

         clock.Start();
      }
   }  
}

 

这个例子非常的经典,基本的关于事件和委托的实质联系都表现了出来

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值