事件的声明格式包括: 完整声明, 简略声明
简略声明是完整声明的语法糖衣,所以掌握事件的完整声明格式,可以了解事件声明的内部结构
事件的完整声明
实现:服务员 订阅,处理【点菜事件】
- 事件模型的5个组成部分
(1)事件的拥有者:顾客
(2)事件:点菜
(3)事件的响应者:服务员
(4)事件处理器:报菜单,记账
(5)订阅事件
思路
(1)准备事件的拥有者——类Customer
在该类中,有 double类型的【属性Bill】,用于存储饭菜花销
有返回值类型为 void 的【实例方法 PayTheBill()】,表示顾客付钱的动作
class Customer
{
public double Bill {
get; set; }
public void PayTheBill()
{
Console.WriteLine("Yummy!I will pay ${0}",this.Bill);
}
}
(2)声明【点菜事件】前应该做什么
明确:事件是基于委托的,这句话的含义是:
<1>事件需要委托类型来约束;该约束既规定了事件能够发送什么样的消息给事件的响应者,也规定了事件的响应者能够收到什么样的事件消息;这就决定了:事件响应者的事件处理器必须能够与该委托类型匹配上,它才能够订阅这个事件
<2>当事件响应者向事件拥有者提供了能够匹配事件的事件处理器之后,需要一个地方保存,记录事件处理器,而能够引用,记录方法的任务只有委托类型的实例能完成
所以,事件这个成员,无论是其表层约束,还是底层实现,都是依赖于委托类型的——“委托是事件的底层基础,事件是委托的上层建筑”
所以为了声明点菜事件,首先需为其准备一个委托
很显然C#类库中并没有为【点菜事件】准备好的委托,我们需要自己声明
(3)声明委托
.NET平台规定:当一个委托是为了声明某个事件所准备的,那么这个委托的名字应使用 【EventHandler】作为后缀
这么做的原因有三个:
<1>表明该委托是用来声明事件的,不是用来封装其他方法的,不应用它做其他的事情
<2>表明该委托是用来约束事件处理器的
<3>表明该委托未来创建的实例,是专门用于存储事件处理器的
所以,该委托的名字应为【OrderEventHandler】,这样的命名规则使得代码的可读性也增强了
//声明委托
pubic delegate void OrderEventHandler(Customer customer,OrderEventArgs e);
(4)声明【OrderEventArgs】
- 上述声明的委托【OrderEventHandler】,它所封装的目标方法的返回值是void,目标方法的第一个参数是 Customer类的实例,第二个参数是 OrderEventArgs类的实例(参数名一般简称为 “e”)
- 由于该委托是用来约束事件处理器的,所以它所封装的方法显然就是事件处理器
- 事件响应者的事件处理器是用来响应【点菜事件】的,它所要做的事情就是:报菜,记账
- 所以,它需要一个 Customer类的实例 作为参数,以便把账单记在顾客头上;需要一个 OrderEventArgs类的实例 作为参数,以便报菜并算账(第二个参数存储顾客所点菜的信息:菜名菜的份量)
- .NET平台规定:用来传递事件消息的类,命名规则应是类名加上EventArgs作为后缀(用意与后缀EventHandler同理),并且应让其派生自EventArgs类
- 应为其声明两个属性:string类型的 DishName,DishSize
class OrderEventArgs:EventArgs
{
public string DishName {
get; set; }
public string DishSize {
get; set; }
}
(5)声明委托类型的字段(是完整声明事件的一部分)
该字段是用来存储,引用事件处理器的;它是上面声明的【OrderEventHandler委托】的一个实例,并且也说过:该委托类型未来的实例,是专门用来存储事件处理器的
private OrderEventHandler ordereventhandler;
(6)声明【点菜(Order)事件】
所有的准备工作都已做好,就可以开始声明事件了
private