昨天,經過《C# 知識回顧 - 事件入門》介紹了事件的定義及簡單用法,今天咱們經過控制檯來看下「發佈 - 訂閱」的基本用法。html
.NET類庫中的全部事件均基於 EventHandler 委託,定義以下: ide
public delegate void EventHandler(object sender, EventArgs e);
你能夠嘗試手動輸入 EventHandler ,而後按下「F12」跳轉到定義:post
.NET 2.0 引入了該委託的一個泛型版本,即 EventHandler<TEventArgs>。ui
【備註】雖然咱們定義的事件能夠基於任何自定的委託類型,但建議使用內置的 EventHandler 進行擴展。
this
1.這裏選擇繼承了 BCL 中的類 EventArgs,能夠在事件的觸發時進行數據的傳遞。
url
1 class MyEventArgs : EventArgs 2 { 3 public string Message { get; private set; } 4 5 public MyEventArgs(string message) 6 { 7 Message = message; 8 } 9 }
2.這裏的第二個參數就是自定義的 MyEventArgs 類型,它繼承了 EventArgs。 spa
delegate void MyEventHandler(object sender, MyEventArgs args);
3.聲明事件的幾種形式:3d
(1)若是沒有自定義 EventArgs 類,你能夠直接使用 C# 中默認提供的非泛型 EventHandler 委託。
code
public event EventHandler MyEvent;
(2)若是使用的是非泛型的 EventHandler,而且寫了一個自定義由 EventArgs 派生的類,可修改以下。xml
public event MyEventHandler MyEvent;
(3)若是使用的是高級的泛型版本,就不須要自定義委託。你只須要簡單地將事件類型指定爲 EventHandler<MyEventArgs>,將尖括號中的內容替換爲本身的類的名稱。
public event EventHandler<MyEventArgs> MyEvent;
下面的示例經過將自定義的 MyEventArgs 類和 EventHandler<TEventArgs> 進行演示:
This is MyEventArgs.cs //事件參數
1 /// <summary> 2 /// 事件參數 3 /// </summary> 4 /// <remarks>一個自定義的類:自定義事件的參數</remarks> 5 class MyEventArgs : EventArgs 6 { 7 public string Message { get; } 8 9 public MyEventArgs(string message) 10 { 11 Message = message; 12 } 13 }
This is Publisher.cs //發佈者
1 /// <summary> 2 /// 事件發佈者 3 /// </summary> 4 class Publisher 5 { 6 //聲明一個泛型事件 7 public event EventHandler<MyEventArgs> MyEvent; 8 9 public void Publish() 10 { 11 Console.WriteLine("Publis is starting"); 12 13 //你能夠在事件觸發前寫些代碼 14 15 OnMyEvent(new MyEventArgs(DateTime.Now.ToString())); 16 } 17 18 /// <summary> 19 /// 觸發事件 20 /// </summary> 21 /// <param name="args"></param> 22 /// <remarks>虛方法,容許子類重寫調用行爲</remarks> 23 protected virtual void OnMyEvent(MyEventArgs args) 24 { 25 //只有在事件訂閱時(!= null),才觸發事件 26 MyEvent?.Invoke(this, args); 27 } 28 }
This is Subscriber.cs //訂閱者
1 /// <summary> 2 /// 訂閱者 3 /// </summary> 4 class Subscriber 5 { 6 public Guid Guid { get; } 7 8 public Subscriber(Publisher publisher) 9 { 10 Guid = Guid.NewGuid(); 11 //使用 C# 2 的語法進行訂閱 12 publisher.MyEvent += Publisher_MyEvent; 13 } 14 15 /// <summary> 16 /// 事件處理程序 17 /// </summary> 18 /// <param name="sender"></param> 19 /// <param name="args"></param> 20 private void Publisher_MyEvent(object sender, MyEventArgs args) 21 { 22 Console.WriteLine($" Message is {args.Message}, Guid is {Guid}."); 23 } 24 }
This is Program.cs //控制檯,用於啓動
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 var publisher = new Publisher(); 6 var subscriber1 = new Subscriber(publisher); 7 var subscriber2 = new Subscriber(publisher); 8 9 //觸發事件 10 publisher.Publish(); 11 12 Console.WriteLine("OK!"); 13 Console.Read(); 14 } 15 }
事件一種是特殊類型的多播委託,只能從聲明它的類中進行調用。這些方法須要預先經過事件訪問器添加到委託的調用列表中,事件訪問器跟咱們平時使用的屬性訪問器,特殊的是他們的名字,事件訪問器被命名爲 add 和 remove。若是在代碼中沒有提供自定義的事件訪問器,編譯器會自動添加事件訪問器。但在某些狀況下,您可能須要提供自定義的行爲。
1 class MyClass 2 { 3 /// <summary> 4 /// 鎖 5 /// </summary> 6 private static object Locker = new object(); 7 8 /// <summary> 9 /// 接口 10 /// </summary> 11 public interface IMyEvent 12 { 13 event EventHandler OnCall; 14 } 15 16 public class MyEvent : IMyEvent 17 { 18 /// <summary> 19 /// 觸發前事件 20 /// </summary> 21 event EventHandler PreEvent; 22 23 public event EventHandler OnCall 24 { 25 add 26 { 27 lock (Locker) 28 { 29 PreEvent += value; 30 } 31 } 32 remove 33 { 34 lock (Locker) 35 { 36 PreEvent += value; 37 } 38 } 39 } 40 } 41 }
《C# 知識回顧 - 委託 delegate》、《C# 知識回顧 - 委託 delegate (續)》
【參考】https://msdn.microsoft.com/zh-cn/library/w369ty8x(v=vs.80).aspx
【參考】微軟官方文檔