首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

.NET 進階技巧:型別安全的 EventHandlerList 泛型實作

     編輯:關於.NET

前言

.NET Framework 提供 EventHandlerList 管理多事件委派,但缺乏型別安全,鍵值為 object 易導致執行期錯誤。本文提供泛型版本 EventHandlerList<T>,編譯期保證鍵值型別正確,消除拼字錯誤風險。

泛型 EventHandlerList<T> 完整實作


public sealed class EventHandlerList : IDisposable
{
    private ListEntry head;

    public EventHandlerList() { }

    // 索引子存取
    public Delegate this[T key]
    {
        get 
        { 
            ListEntry e = Find(key); 
            return e == null ? null : e.m_handler; 
        }
        set 
        { 
            ListEntry e = Find(key); 
            if (e != null) e.m_handler = value; 
            else head = new ListEntry(key, value, head); 
        }
    }

    // 新增處理器 (支援多播)
    public void AddHandler(T key, Delegate value)
    {
        ListEntry e = Find(key);
        if (e != null) e.m_handler = Delegate.Combine(e.m_handler, value);
        else head = new ListEntry(key, value, head);
    }

    // 批次新增
    public void AddHandlers(EventHandlerList listToAddFrom)
    {
        ListEntry current = listToAddFrom.head;
        while (current != null)
        {
            AddHandler(current.m_key, current.m_handler);
            current = current.m_next;
        }
    }

    public void Dispose() { head = null; }

    private ListEntry Find(T key)
    {
        ListEntry found = head;
        while (found != null)
        {
            if (found.m_key.Equals(key)) break;
            found = found.m_next;
        }
        return found;
    }

    public void RemoveHandler(T key, Delegate value)
    {
        ListEntry e = Find(key);
        if (e != null) e.m_handler = Delegate.Remove(e.m_handler, value);
    }

    private sealed class ListEntry
    {
        internal ListEntry m_next;
        internal T m_key;
        internal Delegate m_handler;

        public ListEntry(T key, Delegate handler, ListEntry next)
        {
            m_next = next; m_key = key; m_handler = handler;
        }
    }
}

應用範例:DispatcherCore 事件管理


public class DispatcherCore
{
    readonly EventHandlerList Events = new EventHandlerList();

    public event EventHandler OnReceiveData
    {
        add { Events.AddHandler(EventType.ReceiveData, value); }
        remove { Events.RemoveHandler(EventType.ReceiveData, value); }
    }

    public event EventHandler OnRefreshData
    {
        add { Events.AddHandler(EventType.RefreshData, value); }
        remove { Events.RemoveHandler(EventType.RefreshData, value); }
    }

    private void RaiseEvent(EventType eventType, EventArgs args)
    {
        var handler = Events[eventType] as EventHandler;
        if (handler != null) handler(this, args);
    }

    private enum EventType
    {
        None, ReceiveData, RefreshData, Error, Info
    }
}

優勢比較

特性原版 EventHandlerList泛型 EventHandlerList<T>
鍵值型別objectT (編譯期檢查)
拼字錯誤執行期發現編譯期錯誤
IntelliSense無提示完整列舉提示
重構安全高風險重構自動更新
效能基準無額外開銷

適用場景

  • 類別擁有大量事件 (10+),需集中管理
  • 事件鍵值適合用列舉型別定義
  • 追求程式碼品質、可維護性、重構安全
  • 框架/元件庫開發,對外公開事件模型

擴展建議

  • 加入 RaiseEvent(T key, params object[] args) 便利方法
  • 實作 IEnumerable> 支援列舉
  • 提供 EventHandlerList<TKey, TDelegate> 雙泛型版本
  • 整合弱引用 (WeakReference) 防止記憶體洩漏

查看本欄目

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved