C# EventHandler觀察者模式


C#和java比較: java中使用的是接口。
C#使用委托機制,可以用時 + 運算符進行注冊,直接多播。 而java中是一般是使用一個集合來保存觀察者。

發布者(Publisher)= 被觀察者 (Observable) = 事件源(java中的EventObject,C#中的sender)
訂閱者(Subscriber)=觀察者(Observer)     = 接收者(java中繼承EventLister,接口, 或Observer接口, C#由於委托機制,不需要繼承接口,直接按EventHandler實現回調方法)

在發生其他類或對象關注的事情時,類或對象可通過事件通知它們。發送(或引發)事件的類稱為“發行者”,接收(或處理)事件的類稱為“訂戶”。
在典型的 C# Windows 窗體或 Web 應用程序中,可訂閱由控件(如按鈕和列表框)引發的事件。可使用 Visual C# 集成開發環境 (IDE) 來瀏覽控件發布的事件,選擇要處理的事件。IDE 會自動添加空事件處理程序方法和訂閱事件的代碼。

EventHandler為C#中的預定義委托,專用於表示不生成數據的事件的事件的處理程序方法。
public delegate void EventHandler(
Object sender,
EventArgs e
)
事件具有以下特點:
1.發行者確定何時引發事件,訂戶確定執行何種操作來響應該事件。
2.一個事件可以有多個訂戶。一個訂戶可處理來自多個發行者的多個事件。
3.沒有訂戶的事件永遠不會被調用。
4.事件通常用於通知用戶操作(如:圖形用戶界面中的按鈕單擊或菜單選擇操作)。
5.如果一個事件有多個訂戶,當引發該事件時,會同步調用多個事件處理程序。要異步調用事件,請參見使用異步方式調用同步方法。
6.可以利用事件同步線程。
7.在 .NET Framework 類庫中,事件是基於 EventHandler 委托和 EventArgs 基類的。

下面的示例演示了上述步驟,它將自定義 EventArgs 類和 EventHandler<T> 用作事件類型。

 

namespace ConsoleApplication2
{
    using System;
    using System.Collections.Generic;
 
    // 自定義一個事件類來保存事件信息
    public class CustomEventArgs : EventArgs
    {
        public CustomEventArgs(string s)
        {
            message = s;
        }
        private string message;
 
        public string Message
        {
            get { return message; }
            set { message = value; }
        }
    }
 
    // 廣播事件的類
    class Publisher
    {
        // 使用 EventHandler<T> 聲明一個事件
        public event EventHandler<CustomEventArgs> RaiseCustomEvent;
        //這個方法是做了一些事情。 然后觸發一個事件。
        public void DoSomething()
        {
            //DoSomething…………
            // 你也可以再觸發事件前,執行一些其他的代碼
            OnRaiseCustomEvent(new CustomEventArgs("Did something,hi 這是事件消息"));
        }
        //使用虛方法,讓子類可以重寫。 to allow derived classes to override the event invocation behavior
        protected virtual void OnRaiseCustomEvent(CustomEventArgs e)
        {
            // 定義一個局部變量,已防止最后一個訂閱者剛好在檢查null后取消訂閱
            EventHandler<CustomEventArgs> handler = RaiseCustomEvent;
 
            // 如果沒有 訂閱者(觀察者), 委托對象將為null
            if (handler != null)
            {
                // 格式化事件消息中 的字符串
                e.Message += String.Format(" at {0}", DateTime.Now.ToString());
 
                // 這是最重要的一句。
                // 此時執行的  handler已經是一個多播委托(如果有多個訂閱者或觀察者注冊)。
                // 既然是多播委托,就可以依次調用各個 回調函數 (既然是回調函數,實際的執行就由訂閱者類決定)。
                //這里面傳入一個this, 就代表 事件源(或發布者 或 被觀察者 都一個意思)
                handler(this, e);
            }
        }
    }
 
    //用來注冊事件的類
    class Subscriber
    {
        private string id;
        public Subscriber(string ID, Publisher pub)
        {
            id = ID;
            // 注冊事件,使用C#2.0語法
            //注冊這個動作,應該有訂閱者主動進行,並且可以再后期取消注冊
            pub.RaiseCustomEvent += HandleCustomEvent;
        }
        // 實現回調函數。 在事件發生后,執行什么樣的操作。這里只是簡單的打印信息。
        void HandleCustomEvent(object sender, CustomEventArgs e)
        {
            //這就是實際的操作。
            Console.WriteLine(id + " received this message: {0}", e.Message);
        }
    }
 
    class Class1
    {
        static void Main(string[] args)
        {
            Publisher pub = new Publisher();
            Subscriber sub1 = new Subscriber("sub1", pub);
            Subscriber sub2 = new Subscriber("sub2", pub);
            // 調用這個方法來產生事件
            pub.DoSomething();
            // Keep the console window open
            Console.WriteLine("Press Enter to close this window.");
            Console.ReadLine();
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM