文章目录
- 15.1 发布者和订阅者
- 15.2 源代码组件概览
- 15.3 声明事件
- 15.4 订阅事件
- 15.5 触发事件
- 15.6 标准事件的用法
- 15.6.1 通过扩展 EventArgs 来传递数据
- 15.6.2 移除事件处理程序
- 15.7 事件访问器
15.1 发布者和订阅者
发布者 / 订阅者模式:发布者定义了一系列事件,订阅者可以通过向发布者提供一个方法来“注册”以获取通知。
当事件发生时,发布者“触发事件”,然后执行订阅者提交的所有方法。
![image-20231103180517931](https://img-blog.csdnimg.cn/img_convert/87505b7469dbcad3804f7417c692edaf.png#pic_center)
- 发布者:发布某个事件的类或结构,其他类可以在该事件发生时得到通知。
- 订阅者:注册事件,在事件发生时得到通知的类或结构。
![image-20231103180753626](https://img-blog.csdnimg.cn/img_convert/74554585f2d893b5567a94bac51682f9.png#pic_center)
- 事件提供私有委托的结构化访问,你无法直接访问委托。
- 对事件只能进行添加、删除或调用操作。
- 事件被触发时会调用委托来依次执行列表中的方法。
![image-20231103181031956](https://img-blog.csdnimg.cn/img_convert/2e71d43b0615e512615c20734b116bed.png#pic_center)
15.2 源代码组件概览
需要在事件中使用的代码有以下 5 部分:
- 委托类型声明。
- 事件处理程序声明。
- 事件声明。
- 事件注册。
- 触发事件的代码。
![image-20231103181440334](https://img-blog.csdnimg.cn/img_convert/3ae28c48c8501ddbeb84ae1587ee4c06.png#pic_center)
15.3 声明事件
- 事件声明在一个类中。
- 需要委托类型的名称。
- 声明为 public 以供外部订阅者访问。
- 不能使用 new 创建事件对象。
![image-20231103181639903](https://img-blog.csdnimg.cn/img_convert/a135946f588af15e12b48fac2920d473.png#pic_center)
事件是成员,并不是类型:
- 不能在一段可执行代码中声明事件。
- 必须声明在类或结构中。
- 事件成员被隐式自动初始化为 null。
- BCL 声明了名为 EventHandler 的委托,专门用于系统事件。
15.4 订阅事件
- 使用
+=
运算符为事件添加事件处理程序。 - 事件处理程序可以是以下任意一种:
- 实例方法。
- 静态方法。
- 匿名方法。
- Lambda 表达式。
![image-20231103182013844](https://img-blog.csdnimg.cn/img_convert/f0814cc6b00829513bb655f35afade3e.png#pic_center)
![image-20231103182116181](https://img-blog.csdnimg.cn/img_convert/117aff8312a964b2bbf216fc3042054d.png#pic_center)
15.5 触发事件
- 触发事件前与 null 比较。
- 和调用方法一样使用事件。
![image-20231103182555769](https://img-blog.csdnimg.cn/img_convert/d46b2f7c41ef04171c1f5bb14a12d98d.png#pic_center)
以下示例展示发布者 Incrementer 和订阅者 Dozens 的使用,在 DoCount 方法中,每增加 12 个计数就触发 CountedADozen 事件。
![image-20231103182745213](https://img-blog.csdnimg.cn/img_convert/15561dec829f0bc3c75029c0e1751316.png#pic_center)
![image-20231103182826555](https://img-blog.csdnimg.cn/img_convert/af21c0605aabc1b8f21be9ae617bddc4.png#pic_center)
15.6 标准事件的用法
Windows GUI 编程广泛使用事件,EventHandler 委托类型的声明如下:
![image-20231103183104166](https://img-blog.csdnimg.cn/img_convert/b29700c4ed0854e2ffad59945896b547.png#pic_center)
- 第一个参数用来保存触发事件对象的引用。
- 第二个参数用来保存状态信息。
- EventArgs 不能传递任何数据,通常会被忽略。
- 如果需要传递数据,需要对 EventArgs 进行派生,用合适字段存储数据。
- object 和 EventArgs 总是传入参数的基类,因此可以用于处理所有事件。
15.6.1 通过扩展 EventArgs 来传递数据
自定义如下信息类,类的名称应以 EventArgs 结尾:
![image-20231103183843250](https://img-blog.csdnimg.cn/img_convert/593e6782ab9aca197cca523f020a7ff3.png#pic_center)
![image-20231103183828505](https://img-blog.csdnimg.cn/img_convert/764d394c641a8ff76c5ddb87184f856b.png#pic_center)
使用带泛型的委托以使用自定义信息类:
![image-20231103184021031](https://img-blog.csdnimg.cn/img_convert/5f47e226b9314345c1176e420b6d8d9c.png#pic_center)
![image-20231103184201741](https://img-blog.csdnimg.cn/img_convert/ced6dce218e1a66cdcdc2b9cd45897f3.png#pic_center)
15.6.2 移除事件处理程序
使用 -=
运算符移除事件处理程序。
和委托类似,如果一个处理程序在事件内注册了多次,移除时只移除列表最后一个。
15.7 事件访问器
使用 add
和 remove
访问器可以修改 +=
和 -=
运算符的行为。
- 声明事件访问器看上去和声明属性类似。
- 声明事件访问器后,事件不包含内嵌委托,需要自己实现存储和移除事件的方法。
- 事件访问器没有返回值,为 void 方法。
![image-20231103184600692](https://img-blog.csdnimg.cn/img_convert/80a1edd84ea7460a38477e63d01596b3.png#pic_center)