#define NonRobustThreadSafety
using System;
//触发事件的来源:
//1.用户的操作
//2.系统的状态变化
//3.程序调用
//事件的发送者:触发事件的对象(含有调用事件委托的对象)
//事件的接受者:接受事件的对象(含有事件方法<订阅事件委托的方法>的对象)
//公共语言运行库(CLR)的事件模型建立在委托机制之上。
namespace Event
{
//对外提供事件成员的事件类
internal class MailManager
{
//第1步:定义一个事件参数类型,按照约定,该类型从System.EventArgs类派生,并且该类的名称应按以EventArgs结尾,
// 用于存放所有需要发送给事件通知的接受者的附加信息。
//如果事件不生成数据,则使用事件数据对象的基类 EventArgs,EventArgs 是包含事件数据的类的基类。
//此类不包含事件数据,在事件引发时不向事件处理程序传递状态信息的事件会使用此类,
//可以直接使用EventArgs.Empty,不需要构建一个新的System.EventArgs派生类。
//如果事件处理程序需要状态信息,则应用程序必须从此类派生一个类来保存数据。
//[Serializable]
//public class EventArgs
//{
// public static readonly EventArgs Empty = new EventArgs()
// public EventArgs();
//}
internal class NewMailEventArgs : EventArgs
{
private readonly String m_from, m_to, m_subject;
public NewMailEventArgs(String from, String to, String subject)
{
m_from = from; m_to = to; m_subject = subject;
}
public String From { get { return m_from; } }
public String To { get { return m_to; } }
public String Subject { get { return m_subject; } }
}
//第2步:定义事件委托类型
// 如果事件不生成数据,则使用事件委托的预定义 EventHandler,表示将处理不包含事件数据的事件的方法。
//[Serializable]
//public delegate void EventHandler
//(
// object sender,
// EventArgs e
//);
//事件模式要求sender参数的类型为Object
//事件模式要求委托定义和回调方法将派生自EventArgs的参数命名为e,仅为增加事件模式一致性
//事件模式要求所有的事件处理程序的返回类型都为void
public delegate void NewMailEventHandler(object sender,NewMailEventArgs e);
// 第3步:定义事件成员
public event NewMailEventHandler NewMail;
//C#编译器将这行代码编译成下面内容:但不能显示地调用add和remove方法。
//1.一个被初始化为null的总是私有<Private>的委托类型的字段
// private NewMailEventHandler NewMail = null;
//2.一个允许对象订阅事件的公共方法add_XXX(其中XXX是事件的名称)---add访问器
// public void add_NewMail(NewMailEventHandler value)
// {
// NewMail = (NewMailEventHandler)Delegate.Combine(NewMail,value);
// }
//3.一个允许对象注销事件的公共方法remove_XXX(其中XXX是事件的名称)remove访问器
// public void remove_NewMail(NewMailEventHandler value)
// {
// NewMail = (NewMailEventHandler)Delegate.Remove(NewMail,value);
// }
//4.在元数据中生成一个事件定义的条目
// 第4步:定义触发事件的方法,来通知已订阅事件的对象事件已发生。
// 按照约定该方法是类的一个受保护的虚方法,该类及其派生类中的代码可以调用这个虚方法,
// 该方法的默认实现仅仅检查是否有对象已经订阅了事件
protected virtual void OnNewMail(NewMailEventArgs e)
{
NewMailEventHandler temp = NewMail;
//处于线程安全的考虑,将委托字段保存到一个临时的字段中
if (temp != null) temp(this, e);
}
// 第5步:接收触发事件信息的方法
// 在定义的类中,必须还有一些方法可以将外部的输入转换为引发事件的动作。
public void SimulateNewMail(String from, String to, String subject)
{
//创建事件参数
NewMailEventArgs e = new NewMailEventArgs(from, to, subject);
//调用触发事件的虚方法
OnNewMail(e);
}
}
//包含事件处理方法的类
internal sealed class Fax
{
public Fax(MailManager mm)
{
mm.NewMail += new MailManager.NewMailEventHandler(FaxMsg);
//C#编译器对事件提供了内置的支持,将该行代码翻译成下述代码,生成对事件add_NewMail方法的调用:
//mm.add_NewMail(new MailManager.NewMailEventHandler(this.FaxMsg))
}
private void FaxMsg(Object sender, MailManager.NewMailEventArgs e)
{
Console.WriteLine("Faxing mail message:");
Console.WriteLine(" From={0}, To={1}, Subject={2}",
e.From, e.To, e.Subject);
}
public void Unregister(MailManager mm)
{
mm.NewMail -= new MailManager.NewMailEventHandler(FaxMsg);
//C#编译器对事件提供了内置的支持,将该行代码翻译成下述代码,生成对事件remove_NewMail方法的调用:
//mm.remove_NewMail(new MailManager.NewMailEventHandler(this.FaxMsg))
}
}
//包含事件处理方法的类
internal sealed class Pager
{
public Pager(MailManager mm)
{
mm.NewMail += new MailManager.NewMailEventHandler(SendMsgToPager);
}
private void SendMsgToPager(Object sender, MailManager.NewMailEventArgs e)
{
Console.WriteLine("Sending mail message to pager:");
Console.WriteLine(" From={0}, To={1}, Subject={2}",
e.From, e.To, e.Subject);
}
public void Unregister(MailManager mm)
{
mm.NewMail -= new MailManager.NewMailEventHandler(SendMsgToPager);
}
}
class Event
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
public static void Main()
{
MailManager mm = new MailManager();
Fax fax = new Fax(mm);
Pager pager = new Pager(mm);
mm.SimulateNewMail("Jeffrey", "Kristin", "I Love You!");
fax.Unregister(mm);
mm.SimulateNewMail("Jeffrey", "Mom & Dad", "Happy Birthday.");
}
}
}