.NET的事件模型建立在委托机制之上,透彻的了解了委托才能明白的分析事件。可以说,事件是对委托的封装,从委托的示例中可知,在客户端可以随意对委托进行操作,一定程度上破坏了面向的对象的封装机制,因此事件实现了对委托的封装。
下面,通过将委托的示例进行改造,来完成一个事件的定义过程:
public class Calculator
{
//定义一个CalculateEventArgs,
//用于存放事件引发时向处理程序传递的状态信息
public class CalculateEventArgs: EventArgs
{
public readonly Int32 x, y;
public CalculateEventArgs(Int32 x, Int32 y)
{
this.x = x;
this.y = y;
}
}
//声明事件委托
public delegate void CalculateEventHandler(object sender,CalculateEventArgs e);
//定义事件成员,提供外部绑定
public event CalculateEventHandler MyCalculate;
//提供受保护的虚方法,可以由子类覆写来拒绝监视
protected virtual void OnCalculate(CalculateEventArgs e)
{
if (MyCalculate != null)
{
MyCalculate(this, e);
}
}
//进行计算,调用该方法表示有新的计算发生
public void Calculate(Int32 x, Int32 y)
{
CalculateEventArgs e = new CalculateEventArgs(x, y);
//通知所有的事件的注册者
OnCalculate(e);
}
}
示例中,对计算器模拟程序做了简要的修改,从二者的对比中可以体会事件的完整定义过程,主要包括:
l 定义一个内部事件参数类型,用于存放事件引发时向事件处理程序传递的状态信息,EventArgs是事件数据类的基类。
l 声明事件委托,主要包括两个参数:一个表示事件发送者对象,一个表示事件参数类对象。
l 定义事件成员。
l 定义负责通知事件引发的方法,它被实现为protected virtual方法,目的是可以在派生类中覆写该方法来拒绝监视事件。
l 定义一个触发事件的方法,例如Calculate被调用时,表示有新的计算发生。
一个事件的完整程序就这样定义好了。然后,还需要定义一个事件触发程序,用来监听事件:
//定义事件触发者
public class CalculatorManager
{
//定义消息通知方法
public void Add(object sender, Calculator.CalculateEventArgs e)
{
Console.WriteLine(e.x + e.y);
}
public void Substract(object sender, Calculator.CalculateEventArgs e)
{
Console.WriteLine(e.x - e.y);
}
}
最后,实现一个事件的处理程序:
public class Test_Calculator
{
public static void Main()
{
Calculator calculator = new Calculator();
//事件触发者
CalculatorManager cm = new CalculatorManager();
//事件绑定
calculator.MyCalculate += cm.Add;
calculator.Calculate(100, 200);
calculator.MyCalculate += cm.Substract;
calculator.Calculate(100, 200);
//事件注销
calculator.MyCalculate -= cm.Add;
calculator.Calculate(100, 200);
}
}
如果对设计模式有所了解,上述实现过程实质是Observer模式在委托中的应用,在.NET中对Observer模式的应用严格的遵守了相关的规范。在Windows Form程序开发中,对一个Button的Click就对应了事件的响应,例如:
this.button1.Click += new System.EventHandler(this.button1_Click);
用于将button1_Click方法绑定到button1的Click事件上,当有按钮被按下时,将会触发执行button1_Click方法:
private void button1_Click(object sender, EventArgs e)
{ }
注:
calculator.MyCalculate += cm.Add; //只是事件绑定,不触发(执行)事件
protected virtual void OnCalculate(CalculateEventArgs e) //事件的触发方法,在各处调用此方法时代表触发事件(执行已绑定的所有事件委托)
{
if (MyCalculate != null)
{
MyCalculate(this, e);
}
}