类型安全的EventHandlerList2014-07-03 cnblogs ProJKY我们写一个类时,有时候会在同一个类上添加很多事件,事件很多的话,是不 容易管理的,.NET提供的EventHandlerList可以辅助多个事件的管理,但不方便 的地方是,它不是类型安全的,缺少类型安全,多少用起来担心会出错。经过我的 一番改造,可以将系统提供的EventHandlerList通过泛型提供类型安全的管理。 泛型类EventHandlerList.cs的实现如下:
public sealed class EventHandlerList<T> : IDisposable { 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<T> listToAddFrom) {ListEntry currentListEntry = listToAddFrom.head;while (currentListEntry != null) { AddHandler(currentListEntry.m_key, currentListEntry.m_handler);currentListEntry = currentListEntry.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; }} }
有了它,我们就可以改变多个事件的使用方式,例子类似于下面这个。
public class DispatcherCore{readonly EventHandlerList<EventType> Events = new EventHandlerList<EventType>(); 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 raiseEvent = Events[eventType] as EventHandler; if (raiseEvent != null)raiseEvent(this, args);} // 其它逻辑,在适当的时候调用RaiseEvent private enum EventType{None,ReceiveData,RefreshData,Error,Info,}}
用起来更方便,很难出错。希望对大家有用。