我们写一个类时,有时候会在同一个类上添加很多事件,事件很多的话,是不容易管理的,.NET提供的EventHandlerList可以辅助多个事件的管理,但不方便的地方是,它不是类型安全的,缺少类型安全,多少用起来担心会出错。经过我的一番改造,可以将系统提供的EventHandlerList通过泛型提供类型安全的管理。泛型类EventHandlerList.cs的实现如下:
1 public sealed class EventHandlerList<T> : IDisposable 2 { 3 ListEntry head; 4 5 public EventHandlerList() 6 { } 7 8 public Delegate this[T key] 9 { 10 get{ 11 ListEntry e = Find(key); 12 return e == null ? null : e.m_handler; 13 } 14 set{ 15 ListEntry e = Find(key); 16 if (e != null){ 17 e.m_handler = value; 18 } 19 else { 20 head = new ListEntry(key, value, head); 21 } 22 } 23 } 24 25 public void AddHandler(T key, Delegate value) 26 { 27 ListEntry e = Find(key); 28 if (e != null) { 29 e.m_handler = Delegate.Combine(e.m_handler, value); 30 } 31 else { 32 head = new ListEntry(key, value, head); 33 } 34 } 35 36 public void AddHandlers(EventHandlerList<T> listToAddFrom) 37 { 38 ListEntry currentListEntry = listToAddFrom.head; 39 while (currentListEntry != null) { 40 AddHandler(currentListEntry.m_key, currentListEntry.m_handler); 41 currentListEntry = currentListEntry.m_next; 42 } 43 } 44 45 public void Dispose() 46 { 47 head = null; 48 } 49 50 private ListEntry Find(T key) 51 { 52 ListEntry found = head; 53 while (found != null) { 54 if (found.m_key.Equals(key)) { 55 break; 56 } 57 found = found.m_next; 58 } 59 return found; 60 } 61 62 public void RemoveHandler(T key, Delegate value) 63 { 64 ListEntry e = Find(key); 65 if (e != null) { 66 e.m_handler = Delegate.Remove(e.m_handler, value); 67 } 68 } 69 70 private sealed class ListEntry 71 { 72 internal ListEntry m_next; 73 internal T m_key; 74 internal Delegate m_handler; 75 76 public ListEntry(T key, Delegate handler, ListEntry next) 77 { 78 m_next = next; 79 m_key = key; 80 m_handler = handler; 81 } 82 } 83 }
有了它,我们就可以改变多个事件的使用方式,例子类似于下面这个。
1 public class DispatcherCore 2 { 3 readonly EventHandlerList<EventType> Events = new EventHandlerList<EventType>(); 4 5 public event EventHandler OnReceiveData { 6 add { 7 Events.AddHandler(EventType.ReceiveData, value); 8 } 9 remove { 10 Events.RemoveHandler(EventType.ReceiveData, value); 11 } 12 } 13 14 public event EventHandler OnRefreshData 15 { 16 add{ 17 Events.AddHandler(EventType.RefreshData, value); 18 } 19 remove{ 20 Events.RemoveHandler(EventType.RefreshData, value); 21 } 22 } 23 24 private void RaiseEvent(EventType eventType, EventArgs args) 25 { 26 var raiseEvent = Events[eventType] as EventHandler; 27 28 if (raiseEvent != null) 29 raiseEvent(this, args); 30 } 31 32 // 其它逻辑,在适当的时候调用RaiseEvent 33 34 private enum EventType 35 { 36 None, 37 ReceiveData, 38 RefreshData, 39 Error, 40 Info, 41 } 42 }
用起来更方便,很难出错。希望对大家有用。