事件的主要特点是一对多关联,即一个事件源,多个响应者。在具体技术上,.NETFramework 的事件处理机制是基于多路委托实现的。
public delegate void MyMultiDelegate(int value );//定义委托类型
//事件发布者类
public class Publisher
{
public MyMultiDelegate handlers; //事件响应者清单,定义委托变量(委托变量可以当做函数来使用)
}
//事件响应者类
public class Subscriber
{
//事件处理函数
public void MyMethod(int i )
{
Console.WriteLine(i);
}
}
以下为模拟实现事件响应的代码:
static void Main(string[] args)
{
//一个事件源对象
Publisher p = new Publisher();
//两个事件响应者
Subscriber s1 = new Subscriber();
Subscriber s2 = new Subscriber();
//可以直接调用Delegate类的静态方法组合多个委托
p.handlers = System.Delegate.Combine(p.handlers, new
MyMultiDelegate(s1.MyMethod)) as MyMultiDelegate;
p.handlers = System.Delegate.Combine(p.handlers, new
MyMultiDelegate(s2.MyMethod)) as MyMultiDelegate;
//或调用+=运算符组合委托
//p.handlers += new MyMultiDelegate(s1.MyMethod);
//p.handlers += new MyMultiDelegate(s2.MyMethod);
//最简单的写法
//p.handlers += s1.MyMethod;
//p.handlers += s2.MyMethod;
//直接调用委托变量,代表激发事件
p.handlers(10);
}
上述代码执行到最后一句时,将会调用两个事件响应者s1 和s2 的事件响应函数MyMethod,在控制台窗口输出两个整数:
10
10
上面这个例子中,事件的激发是在Main()函数中引发的(即上述代码的最后一句),而真实的事件不应允许由外界引发,必须由事件源对象自己引发。
为了限制事件的激发只能由事件源对象自己引发,C#引入了一个新的关键字——event,
public delegate void MyMultiDelegate(int value);
//事件发布者类
public class Publisher
{
public event MyMultiDelegate handlers; //定义一个事件
//激发事件
public void FireEvent()
{
handlers(10);
}
}
//事件响应者类
public class Subscriber
{
//事件处理函数
public void MyMethod(int i)
{
Console.WriteLine(i);
}
}
static void Main(string[] args)
{
Publisher p = new Publisher();
Subscriber s1 = new Subscriber();
Subscriber s2 = new Subscriber();
//声明为事件的委托无法直接调用Combine方法
//以下两句将无法通过编译
//p.handlers = System.Delegate.Combine(p.handlers,
new MyMultiDelegate(s1.MyMethod)) as MyMultiDelegate;
//p.handlers = System.Delegate.Combine(p.handlers,
new MyMultiDelegate(s2.MyMethod)) as MyMultiDelegate;
//必须使用+=运算符给事件追加委托
p.handlers+=new MyMultiDelegate(s1.MyMethod);
p.handlers+=new MyMultiDelegate(s2.MyMethod);
//声明为事件的委托也不能直接调用,下面这句无法通过编译
//p.handlers(10);
//只能通过类的公有方法间接地引发事件
p.FireEvent();
}
对比以上两个示例,不难看出事件与多路委托其实大同小异,只不过多路委托允许在事件源对象之外激发事件罢了。