委託

有一家IT公司,董事長不希望自己的僱員在上班時間玩遊戲,但又不可能每時每刻都盯着每個僱員,因此,他希望使用一種新的方式實現監視僱員的效果:如果有僱員違反規定,某個設備或專門的監查人員將自動發出一個消息通知他,董事長只需要在事情發生時進行處理。  
因此,這個用例實際上是兩種類型——董事長類與僱員類——之間的交互,下面的代碼將給讀者展示如何使用委託與事件機制實現這種交互:  
首先,我們需要在董事長類與僱員類之間定義一個委託類型,用於傳遞兩者之間的事件,這個類型就是一個監視設備或專門負責打小報告的監查人員:  
public       delegate       void       DelegateClassHandle();  
定義一個委託的過程類似方法的定義,但它沒有方法體。定義委託一定要添加關鍵字delegate。由於定義委託實際上相當一個類,因此可以在定義類的任何地方定義委託。另外,根據委託的可見性,也可以添加一般的訪問修飾符,如public、private和protected。  
委託的返回值類型爲void,這並非表示委託類型本身帶有返回值,該返回值類型是指委託的目標函數類型,即它委託的一個事件處理函數返回值是void類型。  
新建一個僱員類Employee,其代碼如下:  

C#   codepublic   class   Employee
{
        public   event   DelegateClassHandle   PlayGame;
 
        public   void   Games()
        {
                if   (PlayGame   !=   null)
                {
                        PlayGame();
                }
        }
}

僱員類Employee代碼中定義了一個DelegateClassHandle類型的事件PlayGame,它的定義方式也很特殊,首先必須使用關鍵字event,表示PlayGame是一個事件,同時還必須聲明該事件的委託類型爲DelegateClassHandle,即將來由該類型的委託對象負責通知事件。  
如果有僱員開始玩遊戲,它將執行Games方法,而只要該方法一被調用,就會觸發一個事件PlayGame,然後董事長就會收到這個事件的消息——有人在玩遊戲了。  
董事長類代碼如下,他有一個方法Notify用於接收消息:  

C#   codepublic   class   Admin
{
        public   void   Notify()
        {
                System.Console.WriteLine("someone   is   playing   game");
        }
}

Employee的PlayGame事件如何與Admin的Notify方法關聯起來呢?只需通過事件綁定即可實現,具體過程如下列代碼:  

C#   codeEmployee   employee   =   new   Employee();
Admin   admin   =   new   Admin();
 
employee.PlayGame   +=   new   DelegateClassHandle(admin.Notify);
employee.Games();

請大家注意事件綁定的代碼:  
employee.PlayGame       +=       new       DelegateClassHandle(admin.Notify);  
通過DelegateClassHandle將兩個類的交互進行了綁定,當employee.Games方法調用後,觸發PlayGame事件,而該事件將被委託給admin的Notify方法處理,通知董事長有僱員在上班時間玩遊戲。  
但董事長並不滿足這種簡單的通知,他還想知道究竟是誰在上班時間違反規定。顯然,現在委託對象必須傳遞必要的參數才行,這個要求也可以很容易地辦到。事件的參數可以設置爲任何類型的數據,在.NET框架中,還提供了事件參數基類EventArgs專門用於傳遞事件數據。  
從該EventArgs類派生一個自定義的事件參數類CustomeEventArgs,這個類型將攜帶僱員姓名和年齡信息:  

C#   codepublic   class   CustomeEvetnArgs   :   EventArgs
{
        string   name   =   "";
        int   age   =   0;
        public   CustomeEvetnArgs()
        {   }
        public   string   Name
        {
                get   {   return   this.name;   }
                set   {   this.name   =   value;   }
        }
        public   int   Age
        {
                get   {   return   this.age;   }
                set   {   this.age   =   value;   }
        }
}

修改委託類型DelegateClassHandle的定義,讓其攜帶必要的參數:  
public       delegate       void       DelegateClassHandle(object       sender,       CustomeEvetnArgs       e);  
僱員類的代碼修改後如下:  

C#   codepublic   class   Employee
{
        private   string   _name;
 
        public   string   Name
        {
                get   {   return   _name;   }
                set   {   _name   =   value;   }
        }
        private   int   _age;
 
        public   int   Age
        {
                get   {   return   _age;   }
                set   {   _age   =   value;   }
        }
 
        public   event   DelegateClassHandle   PlayGame;
 
        public   void   Games()
        {
                if   (PlayGame   !=   null)
                {
                        CustomeEvetnArgs   e   =   new   CustomeEvetnArgs();
                        e.Name   =   this._name   ;
                        e.Age   =   this._age;
                        PlayGame(this,   e);
                }
        }
}

在Games方法中,首先新建一個CustomeEventArgs對象,然後設置了必要的屬性Name和Age。  
董事長的通知方法也必須相應地進行修改:  

C#   codepublic   class   Admin
{
        public   void   Notify(object   sender,   CustomeEvetnArgs   e)
        {
                System.Console.WriteLine(e.Name+"   is   "+e.Age.ToString());
        }
}

將兩個類型對象進行關聯的代碼也需要進行相應的修改:  

C#   codeEmployee   employee   =   new   Employee();
employee.Name   =   "Mike";
employee.Age   =   25;
Admin   admin   =   new   Admin();
 
employee.PlayGame   +=   new   DelegateClassHandle(admin.Notify);
employee.Games();

修改後的代碼運行的結果是,當Mike調用Games方法玩遊戲時,會自動觸發PlayGame事件,而該事件攜帶相關信息通知admin,後者的Notify方法將接收到數據並輸出“Mike       is       25”,告訴董事長是Mike,25歲,正在上班時間玩遊戲。  
   
委託是可以多路廣播(Mulitcast)的,即一個事件可以委託給多個對象接收並處理。在上面的用例中,如果有另一位經理與董事長具有同樣的癖好,也可以讓委託對象將僱員的PlayGame事件通知他。  
首先定義經理類:  

C#   codepublic   class   Manager
{
        public   void   Notify(object   sender,   CustomeEvetnArgs   e)
        {
                System.Console.WriteLine(sender.ToString()   +   "-"   +   e.Name);
        }
}

經理Manager類型的Notify方法與Admin一致,他也接受到相應的信息。  
委託的多路廣播綁定的方法仍然是使用+=運算符,其方法如下面的代碼所示:  

C#   codeEmployee   employee   =   new   Employee();
employee.Name   =   "Mike";
employee.Age   =   25;
Admin   admin   =   new   Admin();
Manager   manager   =   new   Manager();
 
employee.PlayGame   +=   new   DelegateClassHandle(admin.Notify);
employee.PlayGame   +=   new   DelegateClassHandle(manager.Notify);
employee.Games();

執行該方法,讀者將看到admin和manager的Notify方法都會被事件通知並調用執行。通過這樣的方法,董事長和經理都會知道Mike在玩遊戲了。  
如果董事長不希望經理也收到這個通知,該如何解除PlayGame對manager的事件綁定呢?同樣非常簡單,在employee.Games方法被調用前執行下列語句即可:  
employee.PlayGame       -=       new       DelegateClassHandle(manager.Notify);  
 

發佈了116 篇原創文章 · 獲贊 2 · 訪問量 29萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章