zoukankan      html  css  js  c++  java
  • .Net Framework中的委托与事件转载

    .Net Framework中的委托与事件

    为什么.Net Framework 中的事件模型有很多的EventArgs参数?

    在回答上面的问题之前,我们先搞懂 .Net Framework的编码规范:

    • 委托类型的名称都应该以EventHandler结束。
    • 委托的原型定义:有一个void返回值,并接受两个输入参数:一个Object 类型,一个 EventArgs类型(或继承自EventArgs)。
    • 事件的命名为 委托去掉 EventHandler之后剩余的部分。
    • 继承自EventArgs的类型应该以EventArgs结尾。

    再做一下说明:

    1. 委托声明原型中的Object类型的参数代表了Subject,也就是监视对象,在本例中是 Heater(热水器)。回调函数(比如Alarm的MakeAlert)可以通过它访问触发事件的对象(Heater)。
    2. EventArgs 对象包含了Observer所感兴趣的数据,在本例中是temperature。

    上面这些其实不仅仅是为了编码规范而已,这样也使得程序有更大的灵活性。比如说,如果我们不光想获得热水器的温度,还想在Observer端(警报器或者显示器)方法中获得它的生产日期、型号、价格,那么委托和方法的声明都会变得很麻烦,而如果我们将热水器的引用传给警报器的方法,就可以在方法中直接访问热水器了。

    符合 .Net Framework 的规范:

    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace Delegate {
        // 热水器
        public class Heater {
           private int temperature;
           public string type = "RealFire 001";       // 添加型号作为演示
           public string area = "China Xian";         // 添加产地作为演示
           //声明委托
           public delegate void BoiledEventHandler(Object sender, BoiledEventArgs e);

          //声明事件
           public event BoiledEventHandler Boiled

           // 定义BoiledEventArgs类,传递给Observer所感兴趣的信息(保存所传递的信息)
           public class BoiledEventArgs : EventArgs {
               public readonly int temperature;
               public BoiledEventArgs(int temperature) {
                  this.temperature = temperature;
               }
           }

           // 可以供继承自 Heater 的类重写,以便继承类拒绝其他对象对它的监视
           protected virtual void OnBoiled(BoiledEventArgs e) {
               if (Boiled != null) { // 如果有对象注册
                  Boiled(this, e);  // 调用所有注册对象的方法
               }
           }
           
           // 烧水。
           public void BoilWater() {
               for (int i = 0; i <= 100; i++) {
                  temperature = i;
                  if (temperature > 95) {
                      //建立BoiledEventArgs 对象。
                      BoiledEventArgs e = new BoiledEventArgs(temperature);
                      OnBoiled(e);  // 调用 OnBolied方法
                  }
               }
           }
        }

        // 警报器
        public class Alarm {
           public void MakeAlert(Object sender, Heater.BoiledEventArgs e) {
               Heater heater = (Heater)sender;     //这里是不是很熟悉呢?
               //访问 sender 中的公共字段
               Console.WriteLine("Alarm:{0} - {1}: ", heater.area, heater.type);
               Console.WriteLine("Alarm: 嘀嘀嘀,水已经 {0} 度了:", e.temperature);
               Console.WriteLine();
           }
        }

        // 显示器
        public class Display {
           public static void ShowMsg(Object sender, Heater.BoiledEventArgs e) {   //静态方法
               Heater heater = (Heater)sender;
               Console.WriteLine("Display:{0} - {1}: ", heater.area, heater.type);
               Console.WriteLine("Display:水快烧开了,当前温度:{0}度。", e.temperature);
               Console.WriteLine();
           }
        }

        class Program {
           static void Main() {
               Heater heater = new Heater();
               Alarm alarm = new Alarm();

               //为事件注册方法(多种方式)
               heater.Boiled += alarm.MakeAlert;   //注册方法
               heater.Boiled += (new Alarm()).MakeAlert;      //给匿名对象注册方法
               heater.Boiled += new Heater.BoiledEventHandler(alarm.MakeAlert);    //也可以这么注册
               heater.Boiled += Display.ShowMsg;       //注册静态方法

               heater.BoilWater();   //烧水,会自动调用注册过对象的方法
           }
        }
    }

    输出为:
    Alarm:China Xian - RealFire 001:
    Alarm: 嘀嘀嘀,水已经 96 度了:
    Alarm:China Xian - RealFire 001:
    Alarm: 嘀嘀嘀,水已经 96 度了:
    Alarm:China Xian - RealFire 001:
    Alarm: 嘀嘀嘀,水已经 96 度了:
    Display:China Xian - RealFire 001:
    Display:水快烧开了,当前温度:96度。
    // 省略 ...

  • 相关阅读:
    智器SmartQ T7实体店试用体验
    BI笔记之SSAS库Process的几种方案
    PowerTip of the Day from powershell.com上周汇总(八)
    PowerTip of the Day2010071420100716 summary
    PowerTip of the Day from powershell.com上周汇总(十)
    PowerTip of the Day from powershell.com上周汇总(六)
    重新整理Cellset转Datatable
    自动加密web.config配置节批处理
    与DotNet数据对象结合的自定义数据对象设计 (二) 数据集合与DataTable
    在VS2003中以ClassLibrary工程的方式管理Web工程.
  • 原文地址:https://www.cnblogs.com/xiaoxxy/p/1898773.html
Copyright © 2011-2022 走看看