C#委托和事件详解(12)

来源:百度文库 编辑:神马文学网 时间:2024/04/27 21:05:21

输出为:

Alarm:嘀嘀嘀,水已经 96 度了:

Alarm:嘀嘀嘀,水已经 96 度了:

Display:水快烧开了,当前温度:96度。

// 省略...

尽管上面的范例很好地完成了我们想要完成的工作,但是我们不仅疑惑:为什么.net Framework 中的事件模型和上面的不同?为什么有很多的EventArgs参数?

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

l 委托类型的名称都应该以EventHandler结束。

l 委托的原型定义:有一个void返回值,并接受两个输入参数:一个Object 类型,一个 EventArgs类型(或继承自EventArgs)。

l 事件的命名为 委托去掉 EventHandler之后剩余的部分。

l 继承自EventArgs的类型应该以EventArgs结尾。

再做一下说明:

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

2. EventArgs 对象包含了Observer所感兴趣的数据,在本例中是temperature。

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

现在我们改写之前的范例,让它符合 .Net Framework 的规范:

以下是引用片段:
   usingSystem;
   usingSystem.Collections.Generic;
   usingSystem.Text;
   namespaceDelegate{
   //热水器
   publicclassHeater{
   privateinttemperature;
   publicstringtype="RealFire001";//添加型号作为演示
   publicstringarea="ChinaXian";//添加产地作为演示
   //声明委托
   publicdelegatevoidBoiledEventHandler(Objectsender,BoliedEventArgse);
   publiceventBoiledEventHandlerBoiled;//声明事件
   //定义BoliedEventArgs类,传递给Observer所感兴趣的信息
   publicclassBoliedEventArgs:EventArgs{
   publicreadonlyinttemperature;
   publicBoliedEventArgs(inttemperature){
   this.temperature=temperature;
   }
   }
   //可以供继承自Heater的类重写,以便继承类拒绝其他对象对它的监视
   protectedvirtualvoidOnBolied(BoliedEventArgse){
   if(Boiled!=null){//如果有对象注册
   Boiled(this,e);//调用所有注册对象的方法
   }
   }
   //烧水。
   publicvoidBoilWater(){
   for(inti=0;i<=100;i++){
   temperature=i;
   if(temperature>95){
   //建立BoliedEventArgs对象。
   BoliedEventArgse=newBoliedEventArgs(temperature);
   OnBolied(e);//调用OnBolied方法
   }
   }
   }
   }
   //警报器
   publicclassAlarm{
   publicvoidMakeAlert(Objectsender,Heater.BoliedEventArgse){
   Heaterheater=(Heater)sender;//这里是不是很熟悉呢?
   //访问sender中的公共字段
   Console.WriteLine("Alarm:{0}-{1}:",heater.area,heater.type);
   Console.WriteLine("Alarm:嘀嘀嘀,水已经{0}度了:",e.temperature);
   Console.WriteLine();
   }
   }
   //显示器
   publicclassDisplay{
   publicstaticvoidShowMsg(Objectsender,Heater.BoliedEventArgse){//静态方法
   Heaterheater=(Heater)sender;
   Console.WriteLine("Display:{0}-{1}:",heater.area,heater.type);
   Console.WriteLine("Display:水快烧开了,当前温度:{0}度。",e.temperature);
   Console.WriteLine();
   }
   }
   classProgram{
   staticvoidMain(){
   Heaterheater=newHeater();
   Alarmalarm=newAlarm();
   heater.Boiled+=alarm.MakeAlert;//注册方法
   heater.Boiled+=(newAlarm()).MakeAlert;//给匿名对象注册方法
   heater.Boiled+=newHeater.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度。

// 省略 ...

总结

在本文中我首先通过一个GreetingPeople的小程序向大家介绍了委托的概念、委托用来做什么,随后又引出了事件,接着对委托与事件所产生的中间代码做了粗略的讲述。

在第二个稍微复杂点的热水器的范例中,我向大家简要介绍了Observer设计模式,并通过实现这个范例完成了该模式,随后讲述了.Net Framework中委托、事件的实现方式。