.Net中的事件(Event)编程模型
该模型包括发送者(Sender)和接收者(Receiver),发送者通过事件(Event)传递某些消息给接收者。一个对象只有在发布某事件后才有权力在该事件到来时通知其它对象,而一个对象只有在登记某事件后才有资格在该事件发生后接受发布事件的对象的通知。注意这里发生的事件是在事件发布者对象里发生的,而这一事件又有必要让另一对象知道,这才有这样的事件模型的存在的基础和必要。
事件“发布”可以理解为声明一个委托(Delegate),并以该委托为类型声明事件。下面是一个例子:
public delegate void (object sender, SomeEventArgs e);
public event SomeEventHandler SomeEvent;
注意这里delegate是声明委托的关键字,它告诉编译器SomeEventHandler是一个委托,sender是事件发送者,而e是发生的事件的有关参数。委托仅仅给出了函数的形式的约定,而没有任何实现。实际上委托是在程序的运行时才创建的,编译时仅给出结构信息。
事件的发布通常由事件发送者对象实现。除此之外,事件发送者还应该实现相应的事件触发机制,通常是名为OnXXX的处理函数,在On函数中调用事件(触发事件)。
事件的接收者对象主要实现事件处理函数,该处理函数的原型必须符合发送者对象“发布”的委托规格。
事件“登记”可以理解为对发送者对象中事件的赋值,通常在主程序中实现。主程序以接收者对象实现的事件处理函数初始化一个新的委托对象,并将此委托对象用“+=”和“-=”操作符对发送者对象中的事件赋值,从而实现事件的“登记”和“取消登记”操作。
关于委托事件赋值的说明:在声明委托事件的对象(本例中为发送者对象)内部可以对事件进行“=”、“-”、“+=”和“-=”等赋值操作,即通过声明对象属性(Property)或者方法(Method)实现。在对象外部只能进行“+=”和“-=”赋值操作,即通过访问公共成员变量实现。
在实现事件编程时,通常还需要实现事件参数类对象,用作传递事件处理函数的参数。
1. 事件参数对象实例
// 信邮件事件参数类
class NewEmailEventArgs : EventArgs
{
string subject;
string message;
public NewEmailEventArgs(string subject, string message)
{
this.subject = subject;
this.message = message;
}
public string Subject
{
get { return (subject); }
}
public string Message
{
get { return (message); }
}
}
2. 发送者对象实例
// 新邮件委派声明(“发布”事件)
public delegate void NewMailEventHandler(object sender, NewEmailEventArgs e);
// 邮件发送类声明
class EmailSender
{
// 新邮件事件声明(“发布”事件)
public event NewMailEventHandler NewMailEvent;
protected void OnNewMail(NewEmailEventArgs e)
{
if (NewMailEvent != null)
NewMailEvent(this, e);
}
// 发送邮件(触发事件)
public void SendMail(string subject, string message)
{
NewEmailEventArgs e = new NewEmailEventArgs(subject, message);
OnNewMail(e);
}
public void SetHandler(NewMailEventHandler handler)
{
NewMailEvent = handler; // 可以利用“=”操作符赋值
}
}
3. 接收者对象实例
// 邮件接收类声明
class EmailReceiver
{
public EmailReceiver(string name)
{
_name = name;
}
// 处理收到新邮件事件的方法(事件处理函数)
public void ComeMail(object sender, NewEmailEventArgs e)
{
Console.WriteLine("This is Receiver {0}, receive a new email: {1} {2}",
_name, e.Subject, e.Message);
}
string _name;
}
4. 主程序实例
class Test
{
public static void Main()
{
EmailSender mySender = new EmailSender(); // 邮件发送者
EmailReceiver myReceiver1 = new EmailReceiver("Receiver1"); // 第一个接受者
EmailReceiver myReceiver2 = new EmailReceiver("Receiver2"); // 第二个接收者
mySender.NewMailEvent += new
NewMailEventHandler(myReceiver1.ComeMail); // 登记邮件事件
mySender.NewMailEvent += new
NewMailEventHandler(myReceiver2.ComeMail); // 登记邮件事件
mySender.SendMail("Hello!", "I am from Sender!!!"); // 发送邮件,多播
mySender.NewMailEvent -= new
NewMailEventHandler(myReceiver2.ComeMail); // 取消登记邮件事件
mySender.SendMail("Hello!", "I am from Sender!!!"); // 再次发送邮件,单播
Console.WriteLine("Press enter to exit.");
Console.ReadLine();
}
}
5. 运行结果
This is Receiver Receiver1, receive a new email: Hello! I am from Sender!!!
This is Receiver Receiver2, receive a new email: Hello! I am from Sender!!!
This is Receiver Receiver1, receive a new email: Hello! I am from Sender!!!
Press enter to exit.