委托 delegate
委托是一种数据结构,它引用静态方法或引用类实例及该类的实例方法。委托可以指向任何和它参数一致的方法,代码示例如下:
//定义委托
public delegate void NameChange(string userName, int age);
//指定要引用的方法
NameChange nam = new NameChange(UserChange); nam("good", 24);
private void UserChange(string userName, int age) { Response.Write(userName + age.ToString()); }
事件 Event
事件是一种模式,搞明白事件首先要弄清楚谁是发布者,谁是订阅者。
下面代码示例中,User就是事件的发布者:
public class Users { public event EventHandler HanderUser; public virtual void OnHandler(EventArgs e) { if (HanderUser != null) { HanderUser(this, e); } } }
下面代码显示如何订阅事件,就是事件的接收者。
protected void Page_Load(object sender, EventArgs e) { Users user = new Users(); user.HanderUser += new EventHandler(user_HanderUser); } void user_HanderUser(object sender, EventArgs e) { Response.Write("事件发生了;"); }
EventHandler和Delegate
EventHandler 是一个预定义的委托,专用于表示不生成数据的事件的事件处理程序方法。如果事件生成数据,则必须提供自己的自定义事件数据类型,并且必须要么创建一个委托,其中第二个参数的类型为自定义类型,要么使用泛型 EventHandler 委托类并用自定义类型替代泛型类型参数。也就是说下面的代码1和代码2是等效的:
代码片段1:
public class Group { public delegate void GroupHandler(object sender, EventArgs e); public event GroupHandler handler; public virtual void OnHandler(EventArgs e) { if (handler != null) { handler(this, e); } } }
代码片段2:
public class Group { public event EventHandler handler; public virtual void OnHandler(EventArgs e) { if (handler != null) { handler(this, e); } } } 使用EventHandler我们默认定义了返回值为空的委托,如果我们需要自定义委托的数据类型,那么就需要使用delegate关键字来自定义事件类型。
利用事件来实现系统的扩展
事件有什么作用,最初在学习事件时,看到了经常举邮件发送的例子。那么在实际应用中,我们通常利用事件来做什么呢?以用户注册为例子,在我们公司的系统中,除了在主系统中写入
写入用户数外,还需要在一个子系统中写入用户数据。
//事件源,也就是事件的发布者 public class Users { public static event EventHandler SaveUserAfter; public virtual void OnHandler(EventArgs e) { if (SaveUserAfter != null) { SaveUserAfter(this, e); } } public void SaveUser(string userName, string password, string email) { OnHandler(new EventArgs()); } }
//事件订阅者,事件发生的接收者 public class Staffers { public Staffers() { //订阅事件 Users.SaveUserAfter += new System.EventHandler(user_SaveUserAfter); } void user_SaveUserAfter(object sender, System.EventArgs e) { throw new Exception("write staffers"); } }
事件的激活和触发
protected void Page_Load(object sender, EventArgs e) { //把订阅事件的对象激活在应用程序中 Staffers staffer = new Staffers(); Users user = new Users(); //触发事件 user.SaveUser("good", "ch-girl.net", "test@ch-girl.net"); }
通过这样的方式,来实现了Users和Staffers的解耦,增加了Users在保存时的扩展性,以后我们需要把User信息保存到更多子系统时,只需要增加一个订阅者然后注册到系统中就行了。
委托与异步编程
public delegate void NameChange(string userName, int age); protected void Page_Load(object sender, EventArgs e) { NameChange name = new NameChange(ShowUserInfo); IAsyncResult result = name.BeginInvoke("good", 23, null, null); Response.Write("Page_load"); } private void ShowUserInfo(string userName, int age) { Thread.Sleep(5000); //Write File }