Effective C# Item22:使用事件定义外发接口

    事件为类型定义了外发接口,C#的事件是建立在委托的基础上的,委托为事件处理器提供了类型安全的函数签名。

    委托要比事件的使用范围广泛,我们可以把事件看做是一种经过了封装的委托,专门用于事件驱动模型。你可以在客户代码中直接调用委托来激发委托指向的函数,而事件不可以,你只能在服务端调用事件,在客户端调用事件是会引发编译错误的。我们来看下面的程序。

ContractedBlock.gifExpandedBlockStart.gif代码
1 public class EventTest
2 {
3 public delegate int Add(int value1, int value2);
4 public event Add AddHandler;
5 public Add AddDelegate;
6
7 public void OutputAddResult(int value1, int value2)
8 {
9 AddHandler(value1, value2);
10 }
11 }
12
13 public class ClientTest
14 {
15 private EventTest m_EventTest;
16
17 public ClientTest()
18 {
19 m_EventTest = new EventTest();
20 m_EventTest.AddHandler += new EventTest.Add(m_EventTest_AddHandler);
21 m_EventTest.AddDelegate = AddDelegate;
22 //the line below will cause compile error.
23 //m_EventTest.AddHandler(1, 1);
24   m_EventTest.AddDelegate(1, 1);
25 }
26
27 private int m_EventTest_AddHandler(int value1, int value2)
28 {
29 return value1 + value2;
30 }
31
32 private int AddDelegate(int value1, int value2)
33 {
34 return value1 + value2;
35 }
36 }
    上述代码也说明对于委托,你不但可以安排谁是它的调用函数,还可以直接调用它;而对于事件,你是不能直接调用的,只能通过某些操作触发。

    .NET针对Event类型的变量,定义了add和remove两个访问器,类似于普通属性中的get和set,通过add和remove,我们可以使用“+=” 或者 “-=”来注册事件或者解除事件。关于add和remove,是由编译器自动为我们生成的,在实际编写代码时,我们应该声明共有事件,然后让编译器来为我们创建add和remove访问器。

    在定义事件或者事件所在的类型中,是不需要知道潜在的客户调用方的信息的,即事件是只能够在服务器端调用,在客户端进行注册实现,但是服务器端是无需知道客户端的信息的,这两者是松耦合的。这里所说的服务器端和客户端,分别表示声明事件的类型和注册事件的类型。

    当我们的类型包含的事件比较多时,仍然采取为每一个事件定义个一个字段的方式,就变的不可取了,这时,我们可以定义一个事件的容器,在运行时,动态的创建事件对象。其中.NET框架内核在Windows控件子系统中包含有这方面的做法示例。

    我们可以查看下面的代码,使用了容器的方式来保存事件的具体信息。

ContractedBlock.gifExpandedBlockStart.gif代码
1 public class Logger
2 {
3 private static System.ComponentModel.EventHandlerList
4 Handlers = new System.ComponentModel.EventHandlerList();
5
6 static public void AddLogger(
7 string system, AddMessageEventHandler ev )
8 {
9 Handlers[ system ] = ev;
10 }
11
12 static public void RemoveLogger( string system )
13 {
14 Handlers[ system ] = null;
15 }
16
17 static public void AddMsg ( string system,
18 int priority, string msg )
19 {
20 if ( ( system != null ) && ( system.Length > 0 ) )
21 {
22 AddMessageEventHandler l =
23 Handlers[ system ] as AddMessageEventHandler;
24
25 LoggerEventArgs args = new LoggerEventArgs(
26 priority, msg );
27 if ( l != null )
28 l ( null, args );
29
30 // The empty string means receive all messages:
31 l = Handlers[ "" ] as AddMessageEventHandler;
32 if ( l != null )
33 l( null, args );
34 }
35 }
36 }
    上述代码会在EventHandlerList集合中存储各个事件处理器,当客户代码关联到一个特定的子系统(或者说Key值)时,新的事件对象就会被创建。对于同一个Key值,其后的请求会返回相同的事件对象,因为容器是一个静态容器。如果我们的类型在其接口中包含有大量的时间,那么我们就应该采用这种事件容易的方式,当客户代码真正关联事件处理器时,我们才会创建事件成员。

 

    总结:我们使用事件来定义类型中的外发接口,任意数量的客户对象都可以将自己的处理器注册到事件上,然后处理它们,这些客户对象不需要在编译时存在,事件也不必非有订阅者才可以正常工作。在C#中使用事件可以对发送者和可能的通知接收者进行解耦,发送者完全可以独立于接收者进行开发。

转载于:https://www.cnblogs.com/wing011203/archive/2010/01/16/1649775.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/262188.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python画菱形的代码_Python打印“菱形”星号代码方法

本人是一名python初学者,刚刚看到一道有趣的python问题,“用python如何在编译器中打印出菱形图案?” 因此决定尝试一下,代码不多,仅供参考。 代码 def printStar(intNum): s "*" spaceLength intNum block…

Ubuntu 14.04.3 LTS 配置 DNS Server

我们目的是用一台局域网机器完成 192.168.1.113 <-->cloudshield.com的解析&#xff0c;指定A记录和CNAME; 0.关于Ubuntu 14.04.2 LTS 下载、安装、更新这里就直接跳过了; 1.下载安装工具 bind9 sudo apt-get install bind9 DNS 配置文件在/etc/bind 目录中。安装bind9后…

php代码加注释_怎么在php中添加注释

注释在写代码的过程中非常重要&#xff0c;好的注释能让你的代码读起来更轻松&#xff0c;在写代码的时候一定要注意注释的规范。php里面常见的几种注释方式&#xff1a;1.文件头的注释&#xff0c;介绍文件名&#xff0c;功能以及作者版本号等信息/***文件名简单介绍**文件功能…

数据库整理

转载于:https://www.cnblogs.com/cuikang/p/5131531.html

GridControl动态添加 颜色列

设计器&#xff1a; 核心代码&#xff1a; DataTable dt new DataTable("UniqueValue");dt.Columns.Add("symbol", typeof(Color));dt.Columns.Add("label",typeof(string));dt.Columns.Add("count",typeof(int));for (int i 0; i &…

代码托管使用指南

2019独角兽企业重金招聘Python工程师标准>>> 开源中国 登录https://git.oschina.net/ 点击 “” 增加新的项目出现创建项目界面&#xff0c;按照提示&#xff0c;输入相应内容点击“管理”显示如下界面 启用svn&#xff0c;输入你所设置的地址。 svn://git.oschin…

php中接口验证失败,php短信验证失败的原因

随着国民经济的高速发展&#xff0c;短信的应用也逐渐商业化&#xff0c;很多企业、商家开始使用php短信接口来进行推广、营销或内部管理&#xff0c;只是个别的商家在应用php短信接口的时候却遇到了短信发送失败的现象&#xff0c;这到底是因为商家操作有误&#xff0c;还是因…

CentOS6.3中挂载NTFS移动硬盘的经历

2019独角兽企业重金招聘Python工程师标准>>> 鄙人当年用PC硬盘做了一个移动硬盘&#xff08;其实并不方便移动&#xff0c;只是外边包装了一个壳子&#xff0c;可以用USB口访问而已&#xff09;&#xff0c;移动硬盘上存放了一些学习资料。某日想把一部分学习资料拿…

如何在vsc上下载php扩展包,正确的 Composer 扩展包安装方法

问题说明我们经常要往现有的项目中添加扩展包&#xff0c;有时候因为文档的错误引导&#xff0c;如下图来自 这个文档 的&#xff1a;composer update 这个命令在我们现在的逻辑中&#xff0c;可能会对项目造成巨大伤害。因为 composer update 的逻辑是按照 composer.json 指定…

python之33个关键字详解_Python解析、提取url关键字的实例详解

解析url用的类库: python2版本&#xff1a; from urlparse import urlparse import urllib python3版本&#xff1a; from urllib.parse import urlparse import urllib.request 研究了不同的url规则发现&#xff1a;只要在搜索关键字是用嫁接的&#xff0c;查询的关键在解析后…

当退出python时是否释放全部内存_python如何释放内存

关于Python中的内存释放问题 首先就不得不提到Python解释器在何种情况下会释放变量的内存。Python引用了内存计数这一简单的计数来控制。 python学习网&#xff0c;大量的免费python视频教程&#xff0c;欢迎在线学习&#xff01; 下面是引用计数的知识&#xff1a; 1) 增加引用…

利用7z来分卷压缩文件

最近做一个发送Email的小工具&#xff0c;里面有个附件的功能&#xff0c; 如果附件太大了&#xff0c;一般都是用winara 分卷压缩的&#xff0c;然后在上传。 如何用程序来实现自动的分卷压缩的呢?因为RAR不是免费的&#xff0c;就上网找了7z 安装好7z,把7z.dll拷贝到程式的目…

LoadRunner 12.02 安装教程及中文语言包安装

注意事项&#xff1a; 安装前&#xff0c;把所有的杀毒软件和防火墙关闭。 若以前安装过LoadRunner,则将其卸载。 安装路径不要带中文字符。 LoadRunner 12已经不再支持xp系统&#xff0c;仅支持win7和win8系统。 一、下载 首先可以在惠普官网下载Loadrunner12安装包。我的Load…

在WPF的TreeView中实现右键选定

在WPF中&#xff0c;TreeView默认情况是不支持右键选定的&#xff0c;也就是说&#xff0c;当右键点击某节点时&#xff0c;是无法选中该节点的。当我们想在TreeViewItem中实现右键菜单时&#xff0c;往往希望在弹出菜单的同时选中该节点&#xff0c;以使得菜单针对选中的节点生…

JavaScript 音频处理库 pico.js

pico.js 实现了实时音频处理的简单 JavaScript 接口。 示例代码&#xff1a; 转载于:https://www.cnblogs.com/shihao/archive/2012/12/08/2809084.html

[转载]项目风险管理七种武器-霸王枪

“小帅&#xff0c;老大对你的项目很关注&#xff0c;听说又拍了新需求&#xff1f;”度教授说道。 “对&#xff0c;不过我已经用离别钩处理了。” “那可能不够&#xff0c;你的项目已经到后期&#xff0c;现在进行需求变更&#xff0c;可能引入巨大的质量风险&#xff0c;这…

python编程入门第一课_python入门前的第一课 python怎样入门

人工智能时代的到来&#xff0c;很多文章说这么一句&#xff1a;“不会python&#xff0c;就不要说自己是程序员”&#xff0c;这说的有点夸张了&#xff0c;但确实觉得目前python这个语言值得学习&#xff0c;而且会python是高薪程序员的必备技能。很多初学Python的同学都面临…

破站www.2637.cn居然敢截持偶的IE!

网上也有很多人中招了&#xff0c;连主页都被改了做http://www.2637.cn/?gba&#xff0c;杀毒后哪个网址还在哪强占做主页&#xff01;重装IE也试过但还是换不到主页&#xff01;可谓是比较顽固的。 偶痛恨的同时&#xff0c;也对其原理有了一些兴趣。这个死东西还不可以被360…

php熊掌号怎么设置json-ld,dedecms织梦系统怎么对接百度熊掌号并添加JSON_LD数据

dedecms织梦系统怎么对接百度熊掌号并添加JSON_LD数据&#xff1f;百度推出的百度熊掌号非常的不错,我的dedecms织梦系统早早就对接好了,它能对你的原创文章进行原创保护,并评出熊掌号搜索指数,熊掌号搜索指数是对你文章的内容质量,用户喜爱、原创能力、活跃表现、领域专注五个…

Java并发编程:volatile关键字解析

2019独角兽企业重金招聘Python工程师标准>>> volatile这个关键字可能很多朋友都听说过&#xff0c;或许也都用过。在Java 5之前&#xff0c;它是一个备受争议的关键字&#xff0c;因为在程序中使用它往往会导致出人意料的结果。在Java 5之后&#xff0c;volatile关键…