C# 事件机制
在所有關于C#事件機制的介紹中,我更傾向于發布者/訂閱者(Publisher/Subscriber)這種描述。理解事件機制并不是一件容易的事情,它所涉及的思想值得我們好好去研究。
 
 本文資源來自《C#與.NET技術平臺實戰演練》——中國青年出版社
 
 談到事件,我們涉及到兩個角色:事件發布者(Publisher)和事件訂閱者(Scriber),也可以說是事件發送者(Sender)和事件接收者(Receiver)的關系。舉個例子來說,市面上目前有許多雜志,雜志的種類也很多。而我只對其中的某些感興趣,那么我就可以向雜志發行商提出訂閱。之后,每當雜志發行時,我就會收到我在雜志發行商那兒訂閱的雜志。在這個關系中,雜志發行商就相當于事件發行者,而我就是事件訂閱者。每當雜志發行時,就觸發了一個發行事件。
用面向對象的語言解釋,這兩者的意義如下:
事件發行者(Publisher)
它是一個對象,且會維護自身的狀態信息。每當狀態信息發生變動時,便觸發一個事件,并通知所有的事件訂閱者。對于雜志發行商來說,每本雜志都有自己的信息在里面,當雜志發行時,我要通知訂閱該雜志的人:雜志已經發行啦,請注意查收!
事件接收者(Receiver)
這個對象要注冊它感興趣的對象,也就是訂閱它自己喜歡的雜志啦。另外,這個對象通常要提供一個事件處理方法,在事件發行者觸發一個事件后,會自動執行這個方法。對于上面所舉的例子來說,也就是我收到雜志后要做什么事情,比如,你可以滿世界地大喊:我收到雜志啦!也可以將雜志收藏起來慢慢欣賞,具體怎么實現完全取決你自己的喜好。
以下是.NET事件處理機制的模型:
?下面給一個簡單的例子,用以闡述事件的思想:
 
?2using?System.Collections.Generic;
?3using?System.Text;
?4
?5namespace?EventDemo
?6{
?7???????public?delegate?void?SalaryCompute();????????//聲明一個代理類
?8
?9???????public?class?Employee
10???????{
11??????????????public?event?SalaryCompute?OnSalaryCompute;?????????//定義事件,將其與代理綁定
12
13??????????????public?virtual?void?FireEvent()???????//觸發事件的方法
14??????????????{
15?????????????????????if?(OnSalaryCompute?!=?null)
16?????????????????????{
17????????????????????????????OnSalaryCompute();??????//觸發事件
18?????????????????????}
19??????????????}
20???????}
21
22???????public?class?HumanResource
23???????{
24??????????????public?void?SalaryHandler()??????????//事件處理函數
25??????????????{
26?????????????????????Console.WriteLine("Salary");?????//只是打印一行字而已
27??????????????}
28
29??????????????public?static?void?Main()
30??????????????{
31?????????????????????Employee?ep?=?new?Employee();
32?????????????????????HumanResource?hr?=?new?HumanResource();
33?????????????????????ep.OnSalaryCompute+=new?SalaryCompute(hr.SalaryHandler);???????//注冊
34?????????????????????ep.FireEvent();????????//觸發事件
35?????????????????????Console.Read();
36??????????????}
37???????}
38}
39 在這個例子中,Employee類相當于一個事件發布者(Publisher),它定義了事件的相關信息,包括定義了一個事件用于計算薪水(OnSalaryCompute),以及一個觸發事件的函數(FireEvent()),為簡單起見,本例沒有加上事件參數。
與之相對應,HumanResource類則相當于一個事件訂閱者(Subscriber),它定義了一個事件處理函數(SalaryHandler()),并用+=將其與事件聯系起來,從而使事件觸發的時候能夠調用我這個方法(在本例中也就是打印一行字啦)。值得注意的一點是,事件處理函數的方法簽名要與代理的方法簽名相同,這是非常重要的一點。
下面將這個例子改造一下,事件參數信息,用以完善事件機制。
?1using?System;
?2using?System.Collections.Generic;
?3using?System.Text;
?4using?System.Threading;
?5
?6namespace?EventDemo
?7{
?8???????public?delegate?void?SalaryCompute(object?sender,MyEventArgs?e);????????//聲明一個代理類
?9
10???????public?class?Employee
11???????{
12??????????????public?event?SalaryCompute?OnSalaryCompute;?????????//定義事件,將其與代理綁定
13
14??????????????public?virtual?void?FireEvent(MyEventArgs?e)???????//觸發事件的方法
15??????????????{
16?????????????????????if?(OnSalaryCompute?!=?null)
17?????????????????????{
18????????????????????????????OnSalaryCompute(this,e);??????//觸發事件
19?????????????????????}
20??????????????}
21???????}
22
23???????public?class?MyEventArgs?:?EventArgs?????????//定義事件參數類
24???????{
25??????????????public?readonly?double?_salary;
26??????????????public?MyEventArgs(double?salary)
27??????????????{
28?????????????????????this._salary?=?salary;
29??????????????}
30???????}
31
32???????public?class?HumanResource
33???????{
34??????????????public?void?SalaryHandler(object?sender,MyEventArgs?e)??????????//事件處理函數,其簽名應與代理簽名相同
35??????????????{
36?????????????????????Console.WriteLine("Salary?is?{0}",e._salary);?????//只是打印一行字而已
37??????????????}
38
39??????????????public?static?void?Main()
40??????????????{
41?????????????????????Employee?ep?=?new?Employee();
42?????????????????????HumanResource?hr?=?new?HumanResource();
43?????????????????????MyEventArgs?e?=?new?MyEventArgs(123.40);
44?????????????????????ep.OnSalaryCompute+=new?SalaryCompute(hr.SalaryHandler);???????//注冊
45?????????????????????for?(;?;?)
46?????????????????????{
47????????????????????????????Thread.Sleep(1000);??????//讓程序“睡”一秒
48????????????????????????????ep.FireEvent(e);????????//觸發事件
49?????????????????????}
50?????????????????????//Console.Read();
51??????????????}
52???????}
53}
54
總結
                            
                        - 上一篇: adb命令 关机与重启
 - 下一篇: 发现了拯救“文献多的一团麻”的工具