CLR 显示实现事件 EventSet内部管理一个字典

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...");
        }
    }
}

 

转载于:https://www.cnblogs.com/kexb/p/5148219.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值