轉自:http://www.cnblogs.com/wudiwushen/archive/2010/04/21/1717378.htmlhtml
今天我接着上面的3篇文章來說一下,爲何咱們在平常的編程活動中遇到這麼多sender,EventArgs e 參數:
protected void Page_Load(object sender, EventArgs e)
{編程
}設計模式
protected void btnSearch_Click(object sender, ImageClickEventArgs e)
{函數
}this
protected void grdBill_RowDataBound(object sender, GridViewRowEventArgs e)
{
}
那他們到底表示什麼呢?編碼
在回答上面的問題以前,咱們先搞懂 .Net Framework的編碼規範:spa
1、委託類型的名稱都應該以EventHandler結束。
2、委託的原型定義:有一個void返回值,並接受兩個輸入參數:一個Object 類型,一個 EventArgs類型(或繼承自EventArgs)。
3、事件的命名爲 委託去掉 EventHandler以後剩餘的部分。
4、繼承自EventArgs的類型應該以EventArgs結尾。設計
這就是微軟編碼的規範,固然這不只僅是規則,而是在這種規則下使程序有更大的靈活性,那咱們就繼續重構第三講的例子,讓他符合微軟的規範。code
代碼
//全部訂閱者【Subscriber】感興趣的對象,也就是e,都要繼承微軟的EventArgs
//本例中訂閱者【也稱觀察者】MrMing,MrZhang他們感興趣的e對象,就是雜誌【magazine】
public class PubEventArgs : EventArgs
{
public readonly string magazineName;
public PubEventArgs()
{
}
public PubEventArgs (string magazineName)
{
this.magazineName = magazineName;
}
}
//發佈者(Publiser)
public class Publisher
{
//聲明一個出版的委託
//這裏多了一個參數sender,它所表明的就是Subject,也就是監視對象,本例中就是Publisher
public delegate void PublishEventHander(object sender ,PubEventArgs e);
//在委託的機制下咱們創建以個出版事件
public event PublishEventHander Publish;
//聲明一個可重寫的OnPublish的保護函數
protected virtual void OnPublish(PubEventArgs e)
{
if (Publish != null)
{
//Sender = this,也就是Publisher
this.Publish(this, e);
}
}
//事件必需要在方法裏去觸發
public void issue(string magazineName)
{
OnPublish(new PubEventArgs(magazineName));
}
}
//Subscriber 訂閱者
public class MrMing
{
//對事件感興趣的事情
public static void Receive(object sender,PubEventArgs e)
{
Console.WriteLine("嘎嘎,我已經收到最新一期的《"+e.magazineName+"》啦!!");
}
}
public class MrZhang
{
//對事件感興趣的事情
public static void Receive(object sender, PubEventArgs e)
{
Console.WriteLine("幼稚,這麼大了,還看《火影忍者》,SB小明!");
Console.WriteLine("這個我定的《"+e.magazineName+"》,哇哈哈!");
}
}
class Story
{
public static void Main(string[] args)
{
//實例化一個出版社
Publisher publisher = new Publisher();
Console.Write("請輸入要發行的雜誌:");
string name = Console.ReadLine();
if (name == "火影忍者")
{
//給這個出火影忍者的事件註冊感興趣的訂閱者,此例中是小明
publisher.Publish += new Publisher.PublishEventHander(MrMing.Receive);
//發佈者在這裏觸發出版火影忍者的事件
publisher.issue("火影忍者");
}
else
{
//給這個出火影忍者的事件註冊感興趣的訂閱者,此例中是小明[另外一種事件註冊方式]
publisher.Publish += MrZhang.Receive;
publisher.issue("環球日報");
}
Console.ReadKey();
}
}
輸入火影忍者後,觸發小明訂閱的事件server
顯示
經過例子我再作一次說明,其實咱們不用把Sender,e想的過於可怕
1、委託聲明原型中的Object類型的參數表明了Subject,也就是監視對象,在本例中是 Publisher(出版社)。。
2、EventArgs 對象包含了Observer所感興趣的數據,在本例中是雜誌。
你們先休息休息,讓大腦放鬆放鬆,先讓咱們看句名人名言:
不少事情就像看A片,看的人以爲很爽,作的人未必!
「中國人的勵志和國外的勵志存在很是大的不一樣,中國的勵志比較鼓勵人立下大志願,臥薪嚐膽,有朝一日成富成貴。而國外的勵志比較鼓勵人勇敢面對現實生活,面對普通人的困境,雖然結果也是成富成貴,但起點不同,相對來講,我以爲後者在操做上更現實,而前者則須要用999個失敗者來堆砌一個成功者的故事。」
好了,咱們接着講咱們的委託與事件,其實若是你們對設計模式精通的話,其實他們關聯的是觀察者(Observer)模式,這裏我就再也不描述什麼是觀察者模式了,只是簡單講一下他們的關聯:
在C#的event中,委託充當了抽象的Observer接口,而提供事件的對象充當了目標對象。委託是比抽象Observer接口更爲鬆耦合的設計。
若是看不懂的話也不要緊,當你們OO達到必定程度了,天然而然就會明白。
最後咱們來看一個咱們平常最最經常使用的觀察者模式:
場景:當咱們用信用卡刷完錢的時候,咱們就會接收到手機短信,或者是電子郵件,其實這就是Observer pattern
代碼
//---本例場景爲當用戶從銀行帳號裏取出錢後,立刻通知電子郵件和發手機短信---
//本例中的訂閱者,也就是觀察者是電子郵件與手機
//發佈者,也就是被監視對象是銀行帳號
//Obverser電子郵件,手機關心的對象e ,分別是郵件地址、手機號碼、取款金額
public class UserEventArgs : EventArgs
{
public readonly string emailAddress;
public readonly string mobilePhone;
public readonly string amount;
public UserEventArgs(string emailAddress, string mobilePhone,string amount)
{
this.emailAddress = emailAddress;
this.mobilePhone = mobilePhone;
this.amount = amount;
}
}
//發佈者,也就是被監視的對象-銀行帳號
class BankAccount
{
//聲明一個處理銀行交易的委託
public delegate void ProcessTranEventHandler(object sender, UserEventArgs e);
//聲明一個事件
public event ProcessTranEventHandler ProcessTran;
protected virtual void OnProcessTran(UserEventArgs e)
{
if (ProcessTran != null)
{
ProcessTran(this, e);
}
}
public void Prcess(UserEventArgs e)
{
OnProcessTran(e);
}
}
//觀察者Email
class Email
{
public static void SendEmail(object sender, UserEventArgs e)
{
Console.WriteLine("向用戶郵箱" + e.emailAddress + "發送郵件:您在"+System.DateTime.Now.ToString()+"取款金額爲"+e.amount);
}
}
//觀察者手機
class Mobile
{
public static void SendNotification(object sender, UserEventArgs e)
{
Console.WriteLine("向用戶手機" + e.mobilePhone + "發送短信:您在" + System.DateTime.Now.ToString() + "取款金額爲" + e.amount);
}
}
//訂閱系統,實現銀行系統訂閱幾個Observer,實現與客戶端的鬆耦合
class SubscribSystem
{
public SubscribSystem()
{
}
public SubscribSystem(BankAccount bankAccount, UserEventArgs e)
{
//如今咱們在銀行帳戶訂閱2個,分別是電子郵件和手機短信
bankAccount.ProcessTran += new BankAccount.ProcessTranEventHandler(Email.SendEmail);
bankAccount.ProcessTran += new BankAccount.ProcessTranEventHandler(Mobile.SendNotification);
bankAccount.Prcess(e);
}
}
class Client
{
public static void Main(string[] args)
{
Console.Write("請輸入您要取款的金額:");
string amount = Console.ReadLine();
Console.WriteLine("交易成功,請取磁卡。");
//初始化e
UserEventArgs user = new UserEventArgs("jinjiangbo2008@163.com", "18868789776",amount);
//初始化訂閱系統
SubscribSystem subject = new SubscribSystem(new BankAccount(), user);
Console.ReadKey();
}
}
控制檯
網上還有個熱水器燒水的OBSERVER PATTERN 也是蠻經典的,你們能夠看看。