文章目录
-
- 15.1 发布者和订阅者
- 15.2 源代码组件概览
- 15.3 声明事件
- 15.4 订阅事件
- 15.5 触发事件
- 15.6 标准事件的用法
-
- 15.6.1 通过扩展 EventArgs 来传递数据
- 15.6.2 移除事件处理程序
- 15.7 事件访问器
15.1 发布者和订阅者
发布者 / 订阅者模式:发布者定义了一系列事件,订阅者可以通过向发布者提供一个方法来“注册”以获取通知。
当事件发生时,发布者“触发事件”,然后执行订阅者提交的所有方法。
图15.1 发布者和订阅者
- 发布者:发布某个事件的类或结构,其他类可以在该事件发生时得到通知。
- 订阅者:注册事件,在事件发生时得到通知的类或结构。
图15.2 事件含有被封装的委托
- 事件提供私有委托的结构化访问,你无法直接访问委托。
- 对事件只能进行添加、删除或调用操作。
- 事件被触发时会调用委托来依次执行列表中的方法。
图15.3 具有一个事件的类结构和术语
15.2 源代码组件概览
需要在事件中使用的代码有以下 5 部分:
- 委托类型声明。
- 事件处理程序声明。
- 事件声明。
- 事件注册。
- 触发事件的代码。
图15.4 使用事件时的 5 个源代码组件
15.3 声明事件
- 事件声明在一个类中。
- 需要委托类型的名称。
- 声明为 public 以供外部订阅者访问。
- 不能使用 new 创建事件对象。
图15.5 声明事件
事件是成员,并不是类型:
- 不能在一段可执行代码中声明事件。
- 必须声明在类或结构中。
- 事件成员被隐式自动初始化为 null。
- BCL 声明了名为 EventHandler 的委托,专门用于系统事件。
15.4 订阅事件
- 使用
+=
运算符为事件添加事件处理程序。 - 事件处理程序可以是以下任意一种:
- 实例方法。
- 静态方法。
- 匿名方法。
- Lambda 表达式。
图15.6 订阅事件的方式
15.5 触发事件
- 触发事件前与服务器托管网 null 比较。
- 和调用方法一样使用事件。
图15.7 触发事件
以下示例展示发布者 Incrementer 和订阅者 Dozens 的使用,在 DoCount 方法中,每增加 12 个计数就触发 CountedADozen 事件。
图15.8 包含发布者和订阅者的完整程序,展示了使用事件所必须的 5 个部分
15.6 标准事件的用法
Windows GUI 编程广泛使用事件,EventHandler 委托类型的声明如下:
图15.9 EventHandler 委托类型声明
- 第一个参数用来保存触发事件对象的引用。
- 第二个参数用来保存状态信息。
- EventArgs 不能传递任何数据,通常会被忽略。
- 如果需要传递数据,需要对 EventArgs 进行派生,用合适字段存储数据。
- object 和 EventArgs 总是传入参数的基类,因此可以用于处理所有事件。
15.6.1 通过扩展 EventArgs 来传递数据
自定义如下信息类,类的名称应以 EventArgs 结尾:
图15.10 自定义信息类
使用带泛型的委托以使用自定义信息类:
图15.11 使用泛型委托以使用自定义信息类
15.6.2 移除事件处理程序
使用 -=
运算符移除事件处理程序。
和委托类似,如果一个处理程序在事件内注册了多次,移除时只移除列表最后一个。
15.7 事件访问器
使用 add
和 remove
访问器可以修改 +=
和 -=
运算符的行为。
- 声明事件访问器看上去和声明属性类似。
- 声明事件访问器后,事件不包含内嵌委托,需要自己实现存储和移除事件的方法服务器托管网。
- 事件访问器没有返回值,为 void 方法。
图15.12 事件访问器
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
这篇文章,我们聊聊消息队列中非常重要的最佳实践之一:消费幂等。 1 基础概念 消费幂等是指:当出现 RocketMQ 消费者对某条消息重复消费的情况时,重复消费的结果与消费一次的结果是相同的,并且多次消费并未对业务系统产生任何负面影响。 例如,在支付场景下,消…