C#中的事件
事件在一些兴趣事件发生的时候,使类或者对象能通知其他的类和对象。
事件的核心功能是通知。
例:《堡垒之夜》下架是一个事件,而事件是一种类型成员(An Event is a member that enables an object or class to provide notifications.)即,没用堡垒之夜就没有堡垒之夜下架。
能够给发生作为主语的事情,就是事件。
事件的功能
事件发生后,通知别人,发生后的效果,才是事件的效果。
将事件发生发送给订阅了事件的订阅者。
架构
事件发生(附带EventArgs作为事件的参数)->相关消息发送给关注者(收到消息即EventArgs)->关注者处理事件,响应事件(EventHandler)
事件模型
五个步骤
- 类要有一个事件成员
- 一群别的类订阅事件
- 本类事件发生了
- 关心的类被一次性通知
- 订阅者们拿着事件参数(可以无参数)做出相应
五个组成部分
事件的拥有者(Event Source)
一定是一个类或者一个对象,谁拥有这个事件,谁就是这个事件的拥有者。
事件(Event)
通知其他类、对象做出相应。不会主动发生,一定是由事件拥有者的内部逻辑触发。
可以通过事件降低耦合性,可以保护事件内部逻辑不被重置。
事件的响应者(Evnet Subscriber)
订阅事件的类、对象们。
事件处理器(Evnet Handler)
事件响应者处理事件的方法(即Methods)。方法必须和时间的委托类型匹配。
事件订阅(+=操作符 订阅关系)
1.事件发生后,通知的一定是订阅了事件的对象们。
2.事件处理器和事件的关系
(本质就是事件处理器的返回值和参表是否和事件的委托类型一致)
3.具体哪个事件处理器来处理这个事件
(因为一个事件响应者,可能有很多个满足约定的事件处理器)
using UnityEngine;
using System.Timers;
using System;
//事件的拥有者:timer
//事件:Elapsed
//事件的响应者:Printer
//事件处理器:Action,MyAction
public class EventEx : MonoBehaviour
{
Timer timer = new Timer();
public static int counter = 0;
public static string displayString = "This string will loop the Length";
void Start()
{
//timer.Elapsed += Printer.MyAction;//简略写法
timer.Elapsed += new ElapsedEventHandler(Printer.MyAction);//真正的写法
timer.Interval = 1000;//1000ms==1s
timer.Start();
}//找到相应的约定 可以看到事件类型是ElapsedEventHandler
public class Printer
{
internal static void MyAction(object sender, ElapsedEventArgs e)
{
Debug.Log(counter++ % displayString.Length);
}
}
}
另有一VS使用的小技巧。
在写EventHandler的时候,需要与Evnet的参数进行匹配,那么是Ctrl+鼠标左键点到定义去看的,但是可以通过截图中先将方法名写出来然后再自动补全的方式进行声明。如图
事件是基于委托的,因为
1.类型兼容:用委托类型来做约束,规定了发送什么消息给订阅者。在事件拥有者的角度上:表明事件拥有者对外部通知什么消息。事件响应者角度来看,要有一个约定。
2.委托delegate来储存方法的引用 当订阅者向拥有者有了匹配的事件处理器,需要记录,储存,保存这个方法,只有委托的实例能够办到。
事件模型的五个组成部分
事件的拥有者:Customer类
事件(event关键字修饰):OnOrder点餐事件
事件的响应者(类):Waiter类
事件处理器(方法-受到约束的方法):TakeAction方法
事件的订阅关系:+=
OrderEventHandler作为委托类单独命名
以视频中Customer类为例。
Customer类中有一个Bill属性作为点单所需要的总价格。此外作为具体保存委托类的一个类存在。
OnOrder()函数作为当前发送的事件存在。
Order()函数作为事件的拥有者内部逻辑触发函数存在。
事件的拥有者
事件声明的完整格式。事件不是一个委托类型的字段。
EventHandler的声明
.net使用事件名+EventHandler作为后缀.
1.一旦使用了,可读性就会更强。
2.且EventHandler本身也是很通用的委托类型。
public delegate void OrderEventHandler(Customer _customer, OrderEventArgs _e);
此外其实可以不用自己声明,而是用已经有的基类EventHandler来解决问题。
public event OrderEventHandler OnOrder;//将该句改为下面一句
public event EventHandler OnOrder;
完整事件声明
private OrderEventHandler orderEventHandler;//委托类型字段
public event OrderEventHandler OnOrder
{
///事件是想让外界访问到的
add