每日一句:我见青山多妩媚,料青山见我应如是
目录
事件
委托和事件的关系?
为什么使用委托类型来声明事件?/为什么事件是基于委托的?
事件的定义
事件的核心功能
事件和事件模型
如何自定义事件
事件
委托和事件的关系?
事件是委托类型字段的包装器、限制器,限制外界对委托类型字段的访问,委托类型字段通过事件包装、限制后,外界只能去访问它的+=、-=操作符(添加/移除事件处理器)
为什么使用委托类型来声明事件?/为什么事件是基于委托的?
【事件拥有者角度】
为了表明事件拥有者能够对外部通知什么样的消息
【事件响应者角度】
一种[约束]事件处理器,能够收到什么样的消息
也约束了我们使用什么方法、签名来处理相应这个事件
并且会去使用委托类型的实例去储存方法的引用,去储存 事件处理器
当事件响应者向事件拥有者,提供了与之匹配的事件的事件处理器,能够记录、引用方法的这个任务,只有委托类型的实例才能做到
【Event事件是基于委托delegate】
- 类型兼容
事件响应者的事件处理器必须和这个约束匹配上,才能够订阅这个事件
- 通过委托去存储方法
记录、存储、保存方法的任务,委托类型实例才能办到
事件无论从表层约束上来说,还是底层实现上来讲,都依赖于委托类型
事件的定义
事件使一个类或者对象去通知其他类,对象们
事件是一个类型成员
事件可以“发生”,通知别人,发生后的效果,才是事件的功能
事件的核心功能
就是将事件的事件参数,也就是事件的相关信息,通知给那些订阅了这个事件的人们
“XX对象拥有了某个事件”或“X类它含有一个事件”——>这个类对象可以通过这个事件,来通知别的对象。如果这个事件发生了,关心、订阅这个事件的其他对象们会被依次的通知到,并且,它们会纷纷的做出响应,这些对象们就会协调统一的工作起来,程序,也会因为这个事件而发生变化
事件和事件模型
五个步骤:
- 我(类)要有一个事件(成员)
- 一群别的类关心,订阅我的事件
- 我的事件发生了
- 关心的类们被一次性通知到
- 被通知到的人,拿着事件参数作出响应
五个组成部分
事件的拥有者 事件的源头,一定是个类(或者对象)
事件 成员类型,核心功能:通知其他类,对象作出响应。事件不会主动发生,一定是由事件拥有者的内部逻辑触发
事件的响应者
事件处理器 处理事件的方法成员
事件订阅(+=操作符)
订阅关系+=
- 事件发生后,通知的一定是[订阅]了事件的对象们
- 事件处理器和事件的关系(本质就是事件处理器的返回值和参表是否和事件的委托类型一致)[C#规定:用于订阅事件的这个事件处理器,必须和事件遵循同一个约定,已经定义好的事件内部都有委托类型]
- 具体哪个事件处理器,处理那个事件
(因为一个事件响应者,可能有很多个满足约定的事件处理器)
例子:功能:每N秒进行一个固定的行为功能(打印信息)
//事件的拥有者:timer
//事件:E lapsed
//事件的响应者:Printer
//事件处理器:MyAction(自定义一个方法)
//事件的订阅关系:+=
public class EventEx:MonoBehaviour
{ Timer timer=new Timer();
private void Start()
{ timer.Elapsed+=Printer.MyAction;}//添加事件处理器的简化写法
【{timer.Elapsed+=new ElapsedEventHandle(委托类型)(Printer.MyAction)}//使用事件处理器,初始化一个新的委托实例】
{事件的拥有者.事件+=事件的响应者.事件处理器}
//Printer类的事件处理器:MyAction订阅了由timer为主体的[Elapsed事件]
public class Printer
{ internal static void MyAction(object sender,ElapsedEventAvags e)
{ Debug.Log(“aaa”);}
}
如何自定义事件
.Net规定,如果这个委托是为了声明某个事件而准备的,这个委托的命名方式
事件名+EventHandler
事件不能在外部直接调用,只有事件的拥有者通过某些内部逻辑才能触发
事件的拥有者【类】Customer类
事件【event关键字修饰】OnOrder事件
事件的响应者【类】Waiter事件
事件处理器【方法_受到约束的方法】TakeAction方法
事件的订阅关系【+=】
public delegate void OrderEventHandler(Customer _customer,OrderEventArgs _e)//为了声明OrOrder事件所使用
public class EventEx:MonoBehaviour
{ Customer customer =new Customer();
Waiter waiter =new Waiter();
private void Start()
{customer.OnOrder+=waiter.TakeAction;}
//事件拥有者的事件成员+=事件响应者的事件处理器(来订阅OnOrder事件)
//事件拥有者的内部逻辑触发的事件
customer.Order();
customer.PayTheBill();
}
public class Customer
{ public float Bill{get;set;}
public void PayTheBill()
{Debug.Log(“I have to pay:”+this.Bill);}
private OrderEventHandler orderEvenHandler;
//声明委托类型的字段,将会去存储,引用副委员的事件处理器
public evnet OrderEventHandler OnOrder//事件声明完整格式
{ add
{orderEventHandler+=value;}
//委托事件+=事件处理器
remove
{orderEventHandler-=value;}
}
public event OrderEventHandler OnOrder;//事件声明简略格式
public void Order()//内部逻辑
{ if(orderEventHandler!=null)
{ orderEventArgs e=new OrderEventArgs();
e.CoffeeName=”Mocha”;
e.CoffeeSize=”Tall”;
e.CoffeePrice=28;
OrderEventHandler(this,e);
}
}
public class OrderEventArgs:EventArgs//存储点餐信息 传递事件参数
{ public string CoffeeName{get;set;}
public string CoffeeSize{get;set;}
public string CoffeePrice{get;set;}
}
}
}
public class Waiter
{ internal void TakeAction(Customer _customer,OrderEvnetArgs _e)
//根据顾客点餐信息传递事件参数计算不同金额
{ flaot finalPrice=0;
switch(_e.CoffeeSize)
{ case”Tall”:
finalPrice=_e.CoffeePrice;
break;
case”Grand”:
finalPrice=_e.CoffeePrice+3;
break;
case”Venti”:
finalPrice=_e.CoffeePrice+6;
break’
}
_custome.Bill+=finalPrice;
}
}
属性是字段的包装器
事件是委托类型字段的包装器
字段能做到的属性都能做;属性能做的,字段不一定都能做
is操作符:检查对象是否与给定的类型兼容
as操作符:用于检查在兼容的引用类型之间执行某些类型的转换
//以上内容听B站宝藏Up主—BeaverJoe的课,做的学习笔记