[我希望大家在看完文章的時候,多做做練習,自己也可以想個場景,動動手,這樣纔會有深刻的印象,不然遺忘的速度非常快]
今天我接着上面的3篇文章來講一下,爲什麼我們在日常的編程活動中遇到這麼多sender,EventArgs e 參數:
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnSearch_Click(object sender, ImageClickEventArgs e)
{
}
protected void grdBill_RowDataBound(object sender, GridViewRowEventArgs e)
{
}
那他們到底表示什麼呢?
在回答上面的問題之前,我們先搞懂 .Net Framework的編碼規範:
一、委託類型的名稱都應該以EventHandler結束。
二、委託的原型定義:有一個void返回值,並接受兩個輸入參數:一個Object 類型,一個 EventArgs類型(或繼承自EventArgs)。
三、事件的命名爲 委託去掉 EventHandler之後剩餘的部分。
四、繼承自EventArgs的類型應該以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();
}
}
輸入火影忍者後,觸發小明訂閱的事件
顯示
通過例子我再做一次說明,其實我們不用把Sender,e想的過於可怕
一、委託聲明原型中的Object類型的參數代表了Subject,也就是監視對象,在本例中是 Publisher(出版社)。。
二、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("[email protected]", "18868789776",amount);
//初始化訂閱系統
SubscribSystem subject = new SubscribSystem(new BankAccount(), user);
Console.ReadKey();
}
}
控制檯
網上還有個熱水器燒水的OBSERVER PATTERN 也是蠻經典的,大家可以看看。
下一講我們要講講,在我們的日常的MES系統開發中,到底在什麼場景用到委託事件,畢竟我們學了這樣的技術,我們必須要用起來,這才有價值嘛!
呵呵!下講,將會更加精彩!
首頁推薦不能放,我就放這裏好了
推薦2篇文章,是關於人生的