如何發佈符合 .NET 指導方針的事件 (C# 程式設計指南)
下列程式示範如何將遵循標準 .NET 模式的事件新增至您的類別和結構。 .NET 類別庫中的所有事件都是以委派為基礎 EventHandler ,其定義如下:
public delegate void EventHandler(object sender, EventArgs e);
注意
.NET Framework 2.0 引進此委派的泛型版本。 EventHandler<TEventArgs> 下列範例示範如何使用這兩種版本。
雖然您定義的類別中的事件可以依據任何有效的委派類型,即使是傳回值的委派,通常建議您使用 EventHandler 以 .NET 模式為基礎事件,如下列範例所示。
名稱 EventHandler
可能會導致混淆,因為它實際上不會處理事件。 EventHandler和 泛型 EventHandler<TEventArgs> 是委派類型。 簽章符合委派定義的方法或 Lambda 運算式是 事件處理常式 ,並在引發事件時叫用。
根據 EventHandler 模式發佈事件
(略過此步驟,如果您不需要使用 event.) 宣告自訂資料的類別,請在發行者和訂閱者類別都可見的範圍中宣告自訂資料的類別,請移至步驟 3a。 然後新增必要的成員來保存自訂事件資料。 在此範例中,會傳回一個簡單的字串。
public class CustomEventArgs : EventArgs { public CustomEventArgs(string message) { Message = message; } public string Message { get; set; } }
(如果您使用 .) 在發行類別中宣告委派的 EventHandler<TEventArgs> 泛型版本,請略過此步驟。 提供結尾為
EventHandler
的名稱。 第二個參數會指定您的自訂EventArgs
類型。public delegate void CustomEventHandler(object sender, CustomEventArgs args);
使用下列其中一個步驟,在發行類別中宣告事件。
如果沒有自訂 EventArgs 類別,Event 類型將會是非泛型的 EventHandler 委派。 因為當您建立 C# 專案時所包含的 System 命名空間中已宣告委派,所以您不需要宣告委派。 將下列程式碼新增至發行者類別。
public event EventHandler RaiseCustomEvent;
如果您使用的是 EventHandler 的非泛型版本,而且有衍生自 EventArgs 的自訂類別,請在發行類別內宣告事件,並使用步驟 2 中的委派作為類型。
public event CustomEventHandler RaiseCustomEvent;
如果您使用的是泛型版本,則不需要自訂委派。 相反地,您會在發行類別中將事件類型指定為
EventHandler<CustomEventArgs>
,來替代角括號之間的類別名稱。public event EventHandler<CustomEventArgs> RaiseCustomEvent;
範例
下列範例使用自訂 EventArgs 類別和 EventHandler<TEventArgs> 作為事件類型,來示範上述步驟。
using System;
namespace DotNetEvents
{
// Define a class to hold custom event info
public class CustomEventArgs : EventArgs
{
public CustomEventArgs(string message)
{
Message = message;
}
public string Message { get; set; }
}
// Class that publishes an event
class Publisher
{
// Declare the event using EventHandler<T>
public event EventHandler<CustomEventArgs> RaiseCustomEvent;
public void DoSomething()
{
// Write some code that does something useful here
// then raise the event. You can also raise an event
// before you execute a block of code.
OnRaiseCustomEvent(new CustomEventArgs("Event triggered"));
}
// Wrap event invocations inside a protected virtual method
// to allow derived classes to override the event invocation behavior
protected virtual void OnRaiseCustomEvent(CustomEventArgs e)
{
// Make a temporary copy of the event to avoid possibility of
// a race condition if the last subscriber unsubscribes
// immediately after the null check and before the event is raised.
EventHandler<CustomEventArgs> raiseEvent = RaiseCustomEvent;
// Event will be null if there are no subscribers
if (raiseEvent != null)
{
// Format the string to send inside the CustomEventArgs parameter
e.Message += $" at {DateTime.Now}";
// Call to raise the event.
raiseEvent(this, e);
}
}
}
//Class that subscribes to an event
class Subscriber
{
private readonly string _id;
public Subscriber(string id, Publisher pub)
{
_id = id;
// Subscribe to the event
pub.RaiseCustomEvent += HandleCustomEvent;
}
// Define what actions to take when the event is raised.
void HandleCustomEvent(object sender, CustomEventArgs e)
{
Console.WriteLine($"{_id} received this message: {e.Message}");
}
}
class Program
{
static void Main()
{
var pub = new Publisher();
var sub1 = new Subscriber("sub1", pub);
var sub2 = new Subscriber("sub2", pub);
// Call the method that raises the event.
pub.DoSomething();
// Keep the console window open
Console.WriteLine("Press any key to continue...");
Console.ReadLine();
}
}
}