iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

1
Software Development

我要轉職成 C# / .NET 工程師系列 第 33

C# 事件(上) - 使用委派來實作事件

這是我的FB粉專,歡迎大家來按讚:長庚的作業簿
還有我的部落格:https://dannyliu.me

C#的事件我在ASP.NET MVC中印像中是沒有看過,envent應該是在視窗程式或WebForm上才會看到?。不過記得以前寫WebForm的過程中,雖然每個控制項都會用到事件,但記得我不用去了解event也可以把專案做起來,猶豫很久還是決定看看這個主題。

今天的內容主要是參考電子書 C#本事 蔡煥麟

事件驅動

  平常我們撰寫程式時,都是自己主動使用某些物件提供的方法來得到結果。相反地,若物件的結果發生時間是隨機不固定的,我們可能不想自己一直主動詢問物件或一直等待,希望物件結果出來後主動通知我們,而物件結果出來這一件事情就是一種事件、一種改變、一種狀態發生,以上描述的這些算是一種事件驅動的程式設計。在WebForm中,每一個按鈕、控制項都是靠使用者點擊後觸發事件來執行後續程式。

發行-訂閱模式

  C#中的事件處理機制或者說.NET中的事件處理機制,整個機制其實是一種設計模式中--發行-訂閱模式(發行者-訂閱者模式),概念是報社推出一份新報紙,會主動推送給有訂閱報紙的客戶,而不是客戶自己跑去問有沒有新報紙可以買。所以說推出新報紙時、發行新報紙時就會觸發事件,將新報紙送給有訂閱報紙的人。

所以在發行-訂閱模式中,就有幾個關鍵內容

  1. 訂閱者
  2. 發行者
  3. 訂閱名冊
  4. (動作)依名冊通知已經訂閱的人

用委派實作發行/訂閱模式的事件機制

  委派是方法的傳遞,我們可以把方法交給委派,由委派來執行我們的方法。相對地,我們可以把訂閱資料地址等資訊包裝成方法傳遞給委派,當事件發生時執行委派來通知我們這些訂閱者。所以使用委派來實作非常方便,可以幫我們接受多筆訂戶資料,而執行委派又能達到通知訂閱者者,幫助我們完成兩個目的。

先定義一個簡單的訂閱者,每個訂閱者都有名字與自己的通知方法:

class 訂閱者
{
	public string 名字 ;

	public void 通知我(string 訊息)
	{
		Console.WriteLine($"我是{名字},我已經收到最新新聞:{訊息}");
	}
}

接下來再實作發行者,並實作委派來通知訂閱對象
這裡就用C#1.0版的委派使用方式先定義委派

public delegate void 通知對象(string 通知內容);

然後再宣告委派型別作為事件來使用,並且我們再撰寫一個新聞投稿方法,當有人投稿了新聞的那一刻,就要觸發事件去通知訂閱新聞的人。所以我定義了報社類別作為發行者如下:

class 報社
{
	public delegate void 通知對象(string 新聞報導);

	public 通知對象 最新新聞;

	public void 投稿新聞(string 新聞稿)
	{
		//觸發事件
		最新新聞.Invoke(新聞稿);
	}
}

以上我們實作了發行者與訂閱者,並且用委派實作的事件驅動程式

接下來是我們的主程式,包含訂閱新聞與投稿新聞來觸發事件:

static void Main(string[] args)
{
	訂閱者 農夫 = new 訂閱者() { 名字 = "農夫" };
	訂閱者 商人 = new 訂閱者() { 名字 = "商人" };
	訂閱者 騎士 = new 訂閱者() { 名字 = "騎士" };

	報社 王國日報 = new 報社();
	//訂閱
	王國日報.最新新聞 += 農夫.通知我;
	王國日報.最新新聞 += 商人.通知我;
	王國日報.最新新聞 += 騎士.通知我;

	while (true)
	{
		Console.WriteLine("請輸入最新消息:");

		string 消息 = Console.ReadLine();

		王國日報.投稿新聞(消息);
	}

}

執行結果:
https://ithelp.ithome.com.tw/upload/images/20191031/20120420JHn6yo7H31.png

退出訂閱

如果要退出訂閱,使用-=

//退出訂閱
王國日報.最新新聞 -= 農夫.通知我;
王國日報.最新新聞 -= 騎士.通知我;

這是我的FB粉專,歡迎大家來按讚:長庚的作業簿
部落格:https://dannyliu.me


上一篇
C# 3.0 擴充方法
下一篇
C# 事件(下) – 加上event關鍵字
系列文
我要轉職成 C# / .NET 工程師34

尚未有邦友留言

立即登入留言