事件在事情發生時通知任意多個對訊息感興趣的客戶。Logger 類別無需預先知道任何感興趣的物件。
Logger 只包含一個事件。大多數 Windows 控制項有許多事件,此時為每個事件添加欄位不可接受。某些情況下程式中實際只定義少量事件。遇到此情況,可修改設計:僅在執行期需要事件時建立。
(譯註:作者明顯傾向只說優點,不說負面影響。事件對效能影響很大,應盡量少用。作者未明說事件負面影響。)
擴充的 Logger 有 System.ComponentModel.EventHandlerList 容器,儲存給定系統應引發的事件物件。更新的 AddMsg() 攜帶參數指示子系統日誌訊息。若子系統有監聽者,事件引發。同樣,若事件監聽者在所有感興趣訊息上監聽,同樣引發:
public class Logger
{
private static System.ComponentModel.EventHandlerList Handlers = new System.ComponentModel.EventHandlerList();
static public void AddLogger(string system, AddMessageEventHandler ev) { Handlers[system] = ev; }
static public void RemoveLogger(string system) { Handlers[system] = null; }
static public void AddMsg(string system, int priority, string msg)
{
if ((system != null) && (system.Length > 0))
{
AddMessageEventHandler l = Handlers[system] as AddMessageEventHandler;
LoggerEventArgs args = new LoggerEventArgs(priority, msg);
if (l != null) l(null, args);
// 空字串表示接收所有訊息
l = Handlers[""] as AddMessageEventHandler;
if (l != null) l(null, args);
}
}
}
此範例在 EventHandlerList 儲存個別事件處理常式,客戶程式碼添加到特定子系統,需要時取回相同事件物件。若開發類別包含大量事件實例,應考慮用事件處理常式集合。客戶附加事件處理常式時,可選擇建立事件成員。.NET 框架內部 System.Windows.Forms.Control 對事件用複雜實現隱藏複雜事件成員欄位。每個事件欄位內部透過存取集合添加/移除實際處理常式。關於 C# 此特殊習慣,原則 49 有更多資訊。
你用事件在類別上定義對外介面:任意數量客戶可添加處理常式到事件並處理。這些物件編譯時不必知道是誰。事件系統也不必知道細節即可合理使用。C# 事件減弱訊息發送者與可能接收者間關係,發送者可設計成與接收者無關。事件是型別發佈動作資訊的標準方法。