事件
事件
事件涉及两类角色,事件发布者和事件订阅者。触发事件的对象称为事件发布者,捕获事件并对其作出响应的对象叫做事件订阅者。
事件和委托的关系
在事件触发以后,事件发布者要发布消息,通知事件订阅者进行事件处理,但事件发布者并不知道要通知哪些事件订阅者,这就需要在发布者和订阅者之间存在一个中介,这个中介就叫委托,委托包含一个调用列表,那么只需要事件发布者有这样一个委托,各个事件订阅者将自己的事件处理程序都加入到该委托的调用列表中,那么事件触发时,发布者只需要调用委托,即可触发订阅者的事件处理程序。
事件就是类成员的一种,只是事件定义中包含一个特殊的关键字event,事件声明的两种方式:采用自定义委托类型;采用EventHandler预定义委托类型。EventHandler签名public delegate void EventHandler(Object sender, EventArgs e);
订阅事件
class Sample
{
public event EventHandler PrintComplete;
public void OnPrintComplete()
{
//if(PrintComplete != null)
//{
// PrintComplete(this, new EventArgs());
//}
//可简化为该行
//事件触发,即委托的调用执行
PrintComplete?.Invoke(this, new EventArgs());
}
public static void Main()
{
Sample sample = new Sample();
Printer printer = new Printer(sample);
sample.OnPrintComplete();
}
}
class Printer
{
public Printer(Sample sample)
{
sample.PrintComplete += ShowMessage;
sample.PrintComplete += SendSMS;
}
public void ShowMessage(object sender, EventArgs args)
{
Console.WriteLine("Print Complete!");
}
public void SendSMS(object sender, EventArgs args)
{
Console.WriteLine("SMS Sended!");
}
}
EventArgs本身不能包含数据,在事件引发时不能传递数据,如果需要传递则需要对其进行扩展,则需要从此类派生一个类来保存信息。但调用时发现其不满足委托的逆变操作,故不能使用,只能通过自定义委托的方式实现。使用方式与EventHandler基本一致。
delegate void PrintDelgate (object sender, PrintEventArgs e);
class PrintEventArgs : EventArgs
{
public string State { get; set; }
public PrintEventArgs(string state)
{
State = state;
}
}
class Sample
{
public event PrintDelgate PrintComplete;
public void OnPrintComplete()
{
//if(PrintComplete != null)
//{
// PrintComplete(this, new EventArgs());
//}
// 可简化为该行
PrintComplete?.Invoke(this, new PrintEventArgs("good"));
}
public static void Main()
{
Sample sample = new Sample();
Printer printer = new Printer(sample);
sample.OnPrintComplete();
}
}
class Printer
{
public Printer(Sample sample)
{
sample.PrintComplete += ShowMessage;
sample.PrintComplete += SendSMS;
}
public void ShowMessage(object sender, PrintEventArgs args)
{
Console.WriteLine("Print Complete!" + args.State);
}
public void SendSMS(object sender, PrintEventArgs args)
{
Console.WriteLine("SMS Sended!" + args.State);
}
}
事件访问器
事件是特殊的多路广播委托,事件默认有一个私有的委托类型变量,用以保存对订阅事件的事件处理方法的引用,此委托类型的变量仅能从事声明该事件的类调用。
public delegate void MyEventHandler(Object sender, EventArgs e);
private MyEventHandler myEventHandler;
public event MyEventHandler PrintComplete
{
add { myEventHandler += value; }
remove { myEventHandler -= value; }
}