using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication5 { public sealed class EventKey { } public sealed class EventSet { //内部管理一个事件的字典,key为每次生成的所以哈希码是不同的,以确认字典的键不会重复 private readonly Dictionary<EventKey, Delegate> m_events = new Dictionary<EventKey, Delegate>(); /// <summary> /// Monitor.Enter线程安全,在指定对象上获取排它锁 /// </summary> /// <param name="eventKey"></param> /// <param name="handle"></param> public void Add(EventKey eventKey,Delegate handle) { //获取指定对象上的排它锁,线程安全,确保我在增加一个键值对的时候不会发生导致线程不安全的情况 Monitor.Enter(m_events); Delegate d; //获取指定键相关联的值,关键是这样可以防止字典的键不存在时,还要写代码去判断键是否存在的情况 m_events.TryGetValue(eventKey, out d); //将两个委托的调用列表链接在一起 m_events[eventKey] = Delegate.Combine(d, handle); //释放指定对象上的排它锁 Monitor.Exit(m_events); } public void Remove(EventKey eventKey, Delegate handler) { Monitor.Enter(m_events); Delegate d; if (m_events.TryGetValue(eventKey, out d)) { //从指定的源上删除某个委托,内部执行多路广播委托,删除后委托链的头部地址会改变 d = Delegate.Remove(d, handler); //删除后还有委托,设置新的头部地址 if (d != null) { m_events[eventKey] = d; } else { m_events.Remove(eventKey); } Monitor.Exit(m_events); } } //激发事件委托 public void Raise(EventKey eventKey, Object sender, EventArgs e) { Delegate d; Monitor.Enter(m_events); m_events.TryGetValue(eventKey,out d); Monitor.Exit(m_events); if (d != null) { d.DynamicInvoke(new object[] {sender,e }); } } } public class FooEventArgs : EventArgs { } public class TypeWithLotsOfEvents { private readonly EventSet m_eventSet = new EventSet(); protected EventSet EventSet { get { return m_eventSet; } } //对于TypeWithLotsOfEvents的每个实例对应的 下列字段key是唯一的 protected static readonly EventKey s_fooEventKey = new EventKey(); public event EventHandler<FooEventArgs> FOO { add { m_eventSet.Add(s_fooEventKey, value); } remove { m_eventSet.Remove(s_fooEventKey, value); } } protected virtual void OnFOO(FooEventArgs e) { m_eventSet.Raise(s_fooEventKey, this, e); } public void SimulateFOO() { OnFOO(new FooEventArgs()); } } class Program { static void Main(string[] args) { TypeWithLotsOfEvents twle = new TypeWithLotsOfEvents(); twle.FOO += Twle_FOO; twle.SimulateFOO(); Console.ReadKey(); } private static void Twle_FOO(object sender, FooEventArgs e) { Console.WriteLine("Hading Foo Event here..."); } } }