.NET事件机制
一, 事件及事件驱动
1,事件的概念
软件事件是对现实生活中的事件的模拟。从面向对象的角度来说,事件是由对象发出的消息,它是一个信号,通知其他对象有事情发生。例如,单击窗体上的某个控件时,控件可能会激发一个Click事件。
激发与相应事件的载体都是对象。激发事件的对象被称为“事件源”,对这个事件进行响应的对象称为“响应者” 响应者必须提供一个“事件响应(或处理)方法”。
2,事件与多路委托
事件的主要特点是一对多的关联,即一个事件源可以有多个响应者。在具体实现上,.NET Framework的事件处理机制是基于多路委托实现的。
先看一个使用多路委托实现事件的实例项目代码如下:
public delegate void MyEventDelegate(int value);
接着定义了EventSource(事件源)和EventResponsor(事件响应源)两个类,注意EventSource类中有一个MyEverntDelegate类型的字段,它将用于引用事件相应的方法。
public delegate void MyEventDelegate(int value);
public class EventSource
{
public MyEventDelegate handlers;//事件响应者清单
}
public class EventResponsor
{
public void MyMethod(int i)//事件响应方法
{
Console.WriteLine(i);
}
}
以下为模板实现事件的响应代码,请注意多个事件响应方法挂接到多路委托变量上的几种方式:
class Class1
{
static void
{
//一个事件源对象
EventSource p = new EventSource();
//创建两个响应者
EventResponsor Responsor1 = new EventResponsor();
EventResponsor Responsor2 = new EventResponsor();
//课连续调用Delegate类的静态方法组合多个委托变量
p.handlers = System.Delegate.Combine(p.handlers, new MyEventDelegate(Responsor1.MyMethod)) as MyEventDelegate;
p.handlers = System.Delegate.Combine(p.handlers, new MyEventDelegate(Responsor2.MyMethod)) as MyEventDelegate;
//或调用+=运算组合委托变量
//p.handlers += new MyEventDelegate(Responsor1.MyMethod);
//p.handlers += new MyEventDelegate(Responsor2.MyMethod);
//最简单的写法
//p.handlers+=Responsor1.MyMethod;
//p.handlers+=Responsor2.MyMethod;
//直接调用委托变量,代表激发事件
p.handlers(10);
}
}
上述代码执行到最后一句的时候,将会调用两个事件响应者Responsor1和Responsor2的事件响应方法MyMtthod,在控制台输出两个整数:
10
10
上面这个例子中,事件的激发是在Main方法中引发的(也即上述代码的最后一句),而真实的事件不应该允许有外界引发,必须有事件源对象自己引发。
为了限制事件的激发只能由事件源对象自己引发,C#引入了一个新的关键字——event。为此需要修改前面例子中的EventSource类
public class EventSource
{
public event MyEventDelegate handlers;//定义一个事件
public void FireEvent()
{
if (handlers != null)//如果有响应者
handlers(10);//激发事件
}
}
与前面不同之处在于EventSource类给handlers字段增加了一个event关键字,并提供了一个新的用于激发事件的方法FireEvent。
以下为模拟实现事件响应的代码:
class Class1
{
static void
{
//一个事件源对象
EventSource p = new EventSource();
//创建两个事件响应者
EventResponsor Responsor1 = new EventResponsor();
EventResponsor Responsor2 = new EventResponsor();
//必须使用+=运算给事件追加委托
p.handlers += new MyEventDelegate(Responsor1.MyMethod);
p.handlers += new MyEventDelegate(Responsor2.MyMethod);
//声明为事件的委托不能直接调用,下面的这句不能通过编译
//p.handlers(10);这能通过累的公有方法间接的引发事件
p.FireEvent();
}
}
请注意上述代码只能使用“+=”给handles事件追加委托,也只能通过类的静态公有方法间接地激发此事件。
对比以上的两个实例,不难看出事件的这两种实现方法大同小异,本质上是一回事,只不过后面的使用多路委托是允许外界直接引发事件罢了
3,。NET事件实现机制剖析