虽然在自定义的类中的事件可基于任何有效委托类型,但是,通常建议使用.NET预定义事件委托类型让事件基于 .NET 标准事件模式
下面是我总结的发布基于 .NET 标准事件模式的4个步骤:第1步:在发布者类中实例化委托事件,并定义一个实例方法,用来调用委托事件(因为委托事件只能通过定义它的类的实例来调用)。
定义发布者类之前可先定义一个用来存储事件数据的类(它必须派生于EventArgs基类),如下:
注意:在方法StartEvent()中,声明了一个变量,来保存事件对象的副本,这样在取得事件对象的副本后,到触发事件时,这段时间内,这个事件副本就不会受其它线程的影响。如:在此期间,其它线程注销了回调方法,那么MyEvent就为null了,这时再触发事件将引发错误。(这就是线程安全的事件,当然还可以通过锁机制,或者为事件对象始终引用一个空方法)
public class MyEventArgs: EventArgs //定义存储事件数据的类 { public int Current{get;set;} } public class Publisher { public event EventHandler<MyEventArgs> MyEvent; //第1步:实例化委托事件 public int Sum{get;set;} public void StartEvent(int a) { var EventCopy = MyEvent; //每次都取一个副本 MyEventArgs args = new MyEventArgs(); args.Current = a; this.Sum += a; if (EventCopy != null) { EventCopy(this,args); //调用事件 } } }第2步:定义订阅者类,在该类中定义和委托事件相匹配的方法(事件触发时,实际要执行的方法)
public class Subscriber { public void Dosomething1(object obj, MyEventArgs e) { Publisher p = (Publisher)obj; Console.WriteLine("Meg: Sum = {0}, Current = {1}", p.sum, e.Current); } public void Dosomething2(object obj, MyEventArgs e) { } }第3步:在客户端代码中,在发布者类的实例上为委托事件注册回调方法
public class MainClass { static void Main() { Publisher p = new Publisher{ Sum = 0 }; Subscriber sub = new Subscriber(); p.MyEvent += sub. Dosomething1; //注册回调方法 p.MyEvent += sub. Dosomething2; p. StartEvent( 5 ); //调用方法,间接触发事件 p.MyEvent -= sub. Dosomething1; //取消注册 } }要点:事件对象其实就是一个委托对象,把事件当委托来看,就比较容易理解了!不要被Event这个单词给蒙蔽了!
介绍完了!下回将介绍C#中的其它一些较难理解的概念!
其实最好把注册事件的代码直接放到订阅者类的构造函数中,这样在实例化一个订阅者时,就自动注册了事件,客户端代码就显得更简洁。
public class Subscriber
{
public Subscriber(Publisher pub)
{
pub.MyEvent += Dosomething1;
pub.MyEvent += Dosomething2;
}
public void Dosomething1(object obj, MyEventArgs e)
{
Publisher p = (Publisher)obj;
Console.WriteLine("Meg: Sum = {0}, Current = {1}", p.sum, e.Current);
}
public void Dosomething2(object obj, MyEventArgs e)
{
}
}
public class MainClass
{
static void Main()
{
Publisher p = new Publisher { Sum = 0 };
Subscriber sub = new Subscriber(p);
p.StartEvent(5); //调用方法,间接触发事件
}
}