博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
CLR via C#(第3版):事件学习(二)显示实现事件
阅读量:6957 次
发布时间:2019-06-27

本文共 3829 字,大约阅读时间需要 12 分钟。

(一)EventKey

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace EventDemo2{    public sealed class EventKey : Object { }}

(二)EventSet

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;namespace EventDemo2{      //显示实现事件    //原因:因为Winform,WPF,Asp.Net提供了约70个事件,但程序员大多用不到。为了高效存储事件委托    //FCL中System.ComponetModel.EventHandlerList(链表且无线程安全)和这里的EventSet类一样的作用    public sealed  class EventSet    {        //私有字典用于维护EvnentKey->Delegate映射              private readonly Dictionary
m_events = new Dictionary
(); //如果一个EvnentKey->Delegate映射(如果EventKey不存在) //或者将一个委托与一个实现的EventKey合并 public void add(EventKey eventKey,Delegate handler) { Monitor.Enter(m_events); Delegate d; m_events.TryGetValue(eventKey,out d); m_events[eventKey]=Delegate.Combine(d,handler); Monitor.Exit(m_events); } //从EventKey(如果存在)删除一个委托,并且 //在删除最后一个委托时删除EventKey->Delegate映射 public void Remove(EventKey eventKey,Delegate handler) { Monitor.Enter(m_events); Delegate d; //调用TryGetValue,确保在尝试从集合中删除一个不存在的EventKey //不会抛出异常 if(m_events.TryGetValue(eventKey,out d)) { d=Delegate.Remove(d,handler); //如果还有委托,就设置新的头部(地址)否者删除EventKey if(d!=null)m_events[eventKey]=d; else m_events.Remove(eventKey); } Monitor.Exit(m_events); } //为指定的EventKey引发事件 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) { //由于字典可能包含几个不同的委托类型 //所以无法再编译是构造一个安全的委托调用 //因此,我调用System.Delegate类型的DynamicInvoke //方法,以一个对象数组的形式向它传递回调方法的参数 //在内部,DynamickInvoke会调用的回调方法查证参数的类型安全,并调用方法 //如果存在类型不匹配的情况,DynamicInvoke会抛出一个异常 d.DynamicInvoke(new Object[]{sender,e}); } } }}

(三)FooEventArgs

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace EventDemo2{       public  class FooEventArgs:EventArgs{}    }

(四)TypeWithLotsOfEvents

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace EventDemo2{    public class TypeWithLotsOfEvents    {        private readonly EventSet m_eventSet = new EventSet();        protected EventSet EventSet { get { return m_eventSet; } }        //构造一个静态只读对象来标识这个事件        //每个对象都有他自己的哈希码,以便对象的集合中查找到这个事件的委托链表        protected static readonly EventKey s_tooEventKey = new EventKey();        //定义事件的访问器方法,用于在集合中增删委托        public event EventHandler
Foo { add { m_eventSet.add(s_tooEventKey, value); } remove { m_eventSet.Remove(s_tooEventKey, value); } } protected virtual void OnFoo(FooEventArgs e) { m_eventSet.Raise(s_tooEventKey, this, e); } //定义将输入转换成这个事件的方法 public void SimulateFoo() { OnFoo(new FooEventArgs()); } }}

(五)代码调用 

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace EventDemo2{    class Program    {        static void Main(string[] args)        {            TypeWithLotsOfEvents twle = new TypeWithLotsOfEvents();            twle.Foo += HandleFooEvent;            //触发事件            twle.SimulateFoo();            Console.ReadKey();        }        private static void HandleFooEvent(object sender, FooEventArgs e)        {            Console.WriteLine("Handling Foo Event here...");                   }    }}

 

 

 

 

转载地址:http://yalil.baihongyu.com/

你可能感兴趣的文章
Python测试登录功能
查看>>
babel插件入门-AST(抽象语法树)
查看>>
ubuntu 16.04下docker的安装
查看>>
web页面渲染(一)
查看>>
roadhog+dva中环境变量的配置
查看>>
js解决0.1+0.2==0.3的问题的几种方法
查看>>
python中#!/usr/bin/python与#!/usr/bin/env python的区别
查看>>
第10章:并发和分布式编程 10.1并发性和线程安全性
查看>>
多线程之死锁就是这么简单
查看>>
Python字符串格式化
查看>>
朴素贝叶斯算法文本分类原理
查看>>
轰轰烈烈的搭建Spring + Spring MVC + Mybatis
查看>>
MySQL 单机多实例
查看>>
微信小程序入门到实战(二)
查看>>
graphql-java使用手册:part4 订阅(Subscriptions)
查看>>
理解js对象
查看>>
2017-10-07 前端日报
查看>>
发展至今的机器学习到底对我们的就业和社会产生了哪些影响?
查看>>
2017四川电商年度盛典,千机网论道企业变革
查看>>
四种方法教你破解Linux(CentOS7.4)系统的root密码
查看>>