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

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

代码

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控件子系统中包含有这方面的做法示例。

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

代码

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

Effective C# Item22:使用事件定义外发接口相关推荐

  1. Effective C# 原则22:用事件定义对外接口(译)

    Effective C# 原则22:用事件定义对外接口 Item 22: Define Outgoing Interfaces with Events 可以用事件给你的类型定义一些外部接口.事件是基于 ...

  2. Postfix疯狂外发垃圾邮件之分析与解决

    本周二上班有人反应公司邮箱无法外发邮件,后来登录到服务器查看原因,不看不知道,一看吓一跳,服务器日志疯狂滚动!一看全是被其它邮件服务器拒绝的信息!由于这台服务器以前不是我管,连配置文件都find了好久 ...

  3. 面向未来,镭速助力企业构建文件安全外发新生态

    你的员工现在在用什么方法外发文件? 日新月异的当今社会,文件外发.共享是企业发展和生产的工具和要求.快速获取信息,高效联动,充分挖掘数据潜在价值,全流程数字化让工作更简单.然而,贯穿全流程的企业数据信 ...

  4. 亿赛通的加密软件对加密图纸文件外发效果如何?

    相比亿赛通的加密软件,我更推荐天锐绿盾透明加密.防泄密软件系统 它由文件加密模块.内网安全模块.外网模块.U盘认证模块.打印控制模块组成,主要功能如下: 加密模块 文件加密模块通过绿盾信息安全管理软件 ...

  5. 如何管控企业文件外发权限?

    在数字化时代,数据安全"重于泰山",尤其是当前的企业运营与互联网息息相关,越来越多的电子文档替代纸质文档的形式存储.发送,电子文档的交流体现在企业各个应用环节,而由于电子文档的特殊 ...

  6. U盘加密软件厂商提醒:实现U盘文件防拷贝、外发文件加密控制

    U盘作为目前企事业单位使用比较广泛的存储介质,在互联网的办公以及文件的外发授权使用中都有重要的使用! 企业机构利用U盘加密能够实现什么样的效果呢?U盘加密软件可以保护企业U盘里的文件不被其他人查看,同 ...

  7. 企业文档易泄密?文件外发管控防止文件泄露....

    文件外发审计 文件外发审计可以记录通过即时通讯工具(WhatApp).电子邮件.网盘.浏览器等途径外发文件日志,还能记录U盘.蓝牙.移动硬盘等移动设备拷贝文件的操作日志: 管理员通过文件操作记录预判泄 ...

  8. django 设置外键_django2.0前后版本定义外键和一对一关系的差别

    概述 Django在根据models生成数据库表时报 __init__() missing 1 required positional argument: 'on_delete',简单记录下解决过程. ...

  9. 流程文件外发同步及加密

    最近PLM项目接近尾声,数据研发部门内部走完流程后需要文件外发,这篇主要说明如何解决外发文件时时性和安全问题,望大神指教: 问题: 1.数据研发部门数据独立2.供应商之间数据独立3.走完流程,加密数据 ...

最新文章

  1. lua学习笔记之数据文件及序列化
  2. 转 23种开发模式一点就通
  3. 一行代码值 200 万?雷军公开小米新 Logo 引吐槽
  4. 跨界会对电商行业造成什么影响
  5. 小米4系统定位服务器地址,小米4原装浏览器怎么开启定位系统
  6. fastapi 基础使用
  7. 自动化运维之saltstack
  8. 计算机综合能力知识,通信工程师中级综合能力常考知识点集锦(三):计算机应用基础...
  9. 传奇服务器端地图链接在哪个文件夹,传奇客户端有新地图,怎样在服务端设置链接?让玩家进去?...
  10. 什么是前端框架,当前主流的前端框架
  11. Matlab加矩形窗程序,基于MATLAB结合矩形窗设计FIR滤波器
  12. 1038: 绝对值最大
  13. 身份证验证判断、身份证正则表达式、15位、18位身份证验证
  14. 浪潮服务器不显示光驱,电脑不从光驱启动怎么办?我是浪潮品牌的机子。
  15. EasyClick adb shell命令大全
  16. 设计模式之禅【代理模式】
  17. UVA-10499 The Land of Justice
  18. 等额本息、等额本金、等本等息概念
  19. MoviePy - 中文文档4-MoviePy实战案例-重新构建15世纪舞蹈视频
  20. RoboMaster机甲大师——视觉组——摄像头的选型与应用

热门文章

  1. CodeForces-1058B B. Vasya and Cornfield
  2. Linux目录遍历实现,列出目录下文件,可使用部分参数
  3. Ubuntu14.04下使用apt-get命令傻瓜式安装ffmepg成功
  4. 64位Ubuntu 12.04下搭建嵌入式Qt(4.8.6)、QtCreator、qvfb过程全记录
  5. Opencv3编程入门学习笔记(三)之访问图像像素的三种方法
  6. shell 删除乱码文件
  7. azure机器学习_Microsoft Azure机器学习x Udacity —第4课笔记
  8. gan简介_GAN简介
  9. 梯度下降优化方法'原理_优化梯度下降的新方法
  10. Win7中的文件关联注册表