C#委託五(自訂事件)

來源:互聯網
上載者:User

標籤:style   blog   http   io   ar   color   os   使用   sp   

事件:

"在發生其他類或對象關注的事情時,類或對象可以通過事件通知他們。發送(或引發)事件的類稱為"發行者",接受(或處理)事件的類稱為"訂戶"。"

上面這句話描述了事件的最本質功能,用於底層通知上層。正常的架構設計都是分層結構,而分層結構有一點很重要的就是底層對於上層的無知,當初這樣設計是為瞭解耦,為了更好的物件導向,但是帶來的問題是如何解決自下而上的資訊流。因為自上而下的調用,我們通過介面就可以搞定一切了,上層可以看到下層提供的服務介面,那麼正常的調用可以保證一路向下,底層調用中層提供的服務介面,中層的服務介面的實現中調用了底層的服務介面,這樣感覺很是完美的設計模式。每一層都不再依賴彼此,隱藏了實現細節。但是現在遇到一個最簡單的問題:如果需要底層來觸發上層的行為,如何?。很多程式員告訴我這個簡單,輪詢啊,底層不斷輪詢這一個事情的發生狀況,如果發生了則啟動一個線程專門去處理這個事情。這種解決方案只需要在底層多開出一個服務介面,該服務介面就是表示目前發生了什麼事情,然後上層定時查看該介面,如果發生則採取相應操作。當然該種解決方案也是一種解決途徑,但是估計你也覺得不好,第一無法即時,因為輪詢,那麼必定存在一個時差問題,也就是常說的回應時間問題。還有就是單獨的輪詢線程需要空間與時間的消耗。最讓人鬱悶還在於這個對於時空的消耗竟然與回應時間是反相關的,總之你想回應時間短,那麼就意味著你不得不浪費大量時空,反之亦然。當然此種方法還要解決多線程衝突的問題,涉及到多線程衝突,鎖解鎖的問題,那麼我覺得就不怕你的邏輯能力有多強,耐心有多大,隨著項目規模的變大,線程的變多,你大腦崩潰那是早晚的事情。   此處我們引入事件模式。

先來看看事件的特徵: ?發行者確定何時引發事件,訂戶確定執行何種操作來響應該事件 ?一個事件可以有多個訂戶。一個訂戶可處理來自多個發行者的多個事件 ?沒有訂戶的事件永遠不會被調用 ?事件通常用於通知使用者操作 ?如果一個事件有多個訂戶,當引發該事件時,會同步調用多個事件處理常式 ?支援非同步呼叫 ?可以利用事件同步線程 ?在 .NET Framework 類庫中,事件是基於 EventHandler 委託和 EventArgs 基類的

C#類庫中內建了一大堆事件,尤其那些控制項。而對於我說到的這個底層觸發上層的問題,那麼絕大多數是需要自訂事件的。(庫中內建事件的使用我就不講了,如果這個你不會的話,未免對不起觀眾了。)所以下面就開始著重講講自訂事件的問題:

事件是類和對象向外界發出的訊息,事件的執行是通過事件委託的方式,調用我們所準備好的處理方法。要響應某些事件並針對某些事件執行我們指定的方法,需要做到以下幾步:

  • 聲明委託、事件
?
///定義一個委託public delegate void TestEventHandler(object sender, TestEventArgs e);///用event關鍵字聲明事件對象public event TestEventHandler TestEvent;

 

  • 添加事件的觸發方法,也就是通知接受者方法
?
//事件觸發的方法protected  void OnTestEvent(TestEventArgs e){    if (TestEvent != null)    {        TestEvent(this, e);    }}

  

  • 添加事件引發方法
?
//引發事件的方法public void RaiseEvent(char keyToRaiseEvent){    TestEventArgs e = new TestEventArgs(keyToRaiseEvent);    OnTestEvent(e);}

  

  • 接受者處本地化回應程式法
?
//定義本地處理事件的方法,他與聲明事件的delegate具有相同的參數和傳回值類型 public void KeyPressed(object sender, TestEventSource.TestEventArgs e){    Console.WriteLine("寄件者:{0},所按得健為:{1}", sender, e.KeyToRaiseEvent);}

  

  • 接受者訂閱事件
?
//訂閱事件 public void Subscribe(TestEventSource evenSource){    evenSource.TestEvent += new TestEventSource.TestEventHandler(KeyPressed);} //取消訂閱事件 public void UnSubscribe(TestEventSource evenSource){    evenSource.TestEvent -= new TestEventSource.TestEventHandler(KeyPressed);}

  最終全部代碼如下:

View Code 
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ConsoleApplication1{    /// <summary>    /// 發布事件類別    /// </summary>    public class TestEventSource    {        /// <summary>        /// 定義事件參數類        /// </summary>        public class TestEventArgs : EventArgs        {            public readonly char KeyToRaiseEvent;            public TestEventArgs(char keyToRaiseEvent)            {                KeyToRaiseEvent = keyToRaiseEvent;            }        }        ///定義一個委託        public delegate void TestEventHandler(object sender, TestEventArgs e);        ///用event關鍵字聲明事件對象        public event TestEventHandler TestEvent;        //事件觸發的方法        protected  void OnTestEvent(TestEventArgs e)        {            if (TestEvent != null)            {                TestEvent(this, e);            }        }        //引發事件的方法        public void RaiseEvent(char keyToRaiseEvent)        {            TestEventArgs e = new TestEventArgs(keyToRaiseEvent);            OnTestEvent(e);        }    }    //監聽事件類別    public class TestEventListener     {        //定義本地處理事件的方法,他與聲明事件的delegate具有相同的參數和傳回值類型         public void KeyPressed(object sender, TestEventSource.TestEventArgs e)        {            Console.WriteLine("寄件者:{0},所按得健為:{1}", sender, e.KeyToRaiseEvent);        }        //訂閱事件         public void Subscribe(TestEventSource evenSource)        {            evenSource.TestEvent += new TestEventSource.TestEventHandler(KeyPressed);        }        //取消訂閱事件         public void UnSubscribe(TestEventSource evenSource)        {            evenSource.TestEvent -= new TestEventSource.TestEventHandler(KeyPressed);        }     }    class Program    {        static void Main(string[] args)        {            ///建立事件來源對象            TestEventSource es = new TestEventSource();            ///建立監聽對象            TestEventListener el = new TestEventListener();            ///訂閱事件            Console.WriteLine("訂閱事件\t");            el.Subscribe(es);            ///引發事件            Console.WriteLine("輸入一個字元,再按enter鍵");            string str = Console.ReadLine();            es.RaiseEvent(str.ToCharArray()[0]);            //取消訂閱事件             Console.WriteLine("\n取消訂閱事件\n");            el.UnSubscribe(es);            //引發事件             Console.WriteLine("輸入一個字元,再按enter健");            str = Console.ReadLine();            es.RaiseEvent(str.ToCharArray()[0]);            Console.ReadLine();        }    }}
 

賦值粘貼即可以執行,且看下面執行效果:

 

C#委託五(自訂事件)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.