委托与事件-事件详解(二)
前言
上一节我们了解学习了委托,委托是类型安全的类,它定义了返回类型和参数的类型。委托类不仅包含对方法的引用,也可以包含对多个方法的引用。
理解委托的一种好的方式是把委托视为是给方法的签名和返回类型指定名称。
今天我们继续来了解委托和事件,现在我们来了解学习一下事件详解。
事件
事件基于委托,为委托提供了一种发布/订阅机制,在.Net中随处可见到这种事件,例如在应用程序中,Button类提供了Click事件,这类事件就是委托。
既然事件是为委托提供了发布/订阅机制,那么肯定设计到两个角色,发布者以及订阅者。
事件发布者(Publisher)--事件的发布者就是一个对象,这个对象维护自身的状态信息,一旦自身的状态信息发生了改变,那么便触发一个事件
事件订阅者(Subscriber)--对事件感兴趣的对象,也可以叫做Receiver,可以注册感兴趣的事件,在触发一个事件后自动执行这段代码。
到底事件的一个怎么运行过程呢?在介绍此过程中我们先看下委托与事件的微软编码规范吧。
一、上一节讲了委托的命名需以EventHandler结束
二、委托原型的定义是一个void返回值而且有两个参数,一个object类型,一个EventArgs类型(或者继承此类型的)
三、事件的命令是委托去掉后缀EventHandler
四、继承了EventArgs需以EventArgs结尾
下面我们一起来看一个简单的委托与事件案例
委托与事件简单实例讲解
假设现在电信公司提供一个话费流量查询的功能,但是其中小明仅关心流量,小红仅关心话费,小李关心话费和流量。现在设计一段他们查询流量和话费的功能。
分析下,他们关心感兴趣的是流量多少,话费多少。--订阅者
输入查询触发事件,反馈流量多少,话费多少。--发布者
/// <summary>
/// 所有订阅者(Subscriber)感兴趣的对象,本列中订阅者感兴趣的对象是流量话费及多少 /// </summary>
public class PubEventArgs : EventArgs
{ /// <summary>
/// 话费或者流量具体值 /// </summary>
public readonly string mobleType; public PubEventArgs()
{
} public PubEventArgs(string mobleType)
{ this.mobleType = mobleType;
}
} /// <summary>
/// 发布者(publiser) /// </summary>
public class Publiser
{ //先定义委托
public delegate void PublishEventHandler(object sender,PubEventArgs e); /// <summary>
/// 定义事件,命名为委托去除EventHandler /// </summary>
public event PublishEventHandler Publish; /// <summary>
/// 执行函数 /// </summary>
/// <param name="e"></param>
public void OnPublish(PubEventArgs e)
{ if (Publish!=null)
{ this.Publish(this,e);
}
} /// <summary>
/// 事件的触发 /// </summary>
/// <param name="mobleType"></param>
public void Use( string mobleType)
{
OnPublish(new PubEventArgs(mobleType));
}
} /// <summary>
/// 订阅者(Subscriber)小明 /// </summary>
public class XiaoMing
{ public static void Receive(object sender, PubEventArgs e)
{
Console.WriteLine($"您的{e.mobleType}剩余100G");
}
} public class XiaoHong
{ public static void Receive(object sender,PubEventArgs e)
{
Console.WriteLine($"您的{e.mobleType}余额为100元");
}
} public class XiaoLi
{ public static void Receive(object sender, PubEventArgs e)
{
Console.WriteLine($"您的流量剩余100G,您的话费余额为100元");
}
} /// <summary>
/// 小明订阅了流量 小红订阅了话费 小李订阅了话费流量。分别查询自己所订阅的,主流程编写 /// </summary>
class Program
{ static void Main(string[] args)
{ //实例化一个发布者
Publiser publiser = new Publiser();
Console.WriteLine("请输入您需要查询的业务:"); string mobleType=Console.ReadLine(); if (mobleType=="流量")
{ //事件注册
publiser.Publish += XiaoMing.Receive;
} else if (mobleType=="话费")
{
publiser.Publish += XiaoHong.Receive;
} else {
publiser.Publish += XiaoLi.Receive;
} //调用触发事件
publiser.Use(mobleType);
}
}
在Main函数中,进行一个事件的注册,例如小明,进来Main函数,实例化一个发布者,在发布者中绑定了小明的订阅事件,然后调用发布者触发事件的方法。
发布者:
一、声明一个委托
二、基于委托声明一个事件
三、一个判断事件是否为空,然后开始执行处理事件
四、一个调用用来触发事件的方法
//先定义委托
public delegate void PublishEventHandler(object sender,PubEventArgs e); /// <summary>
/// 定义事件,命名为委托去除EventHandler /// </summary>
public event PublishEventHandler Publish;
//事件注册
publiser.Publish += XiaoMing.Receive;
订阅者:
感兴趣的事件,最后的输出。
订阅者感兴趣的对象:
用来保存处理订阅者感兴趣的对象。
总结
我们仔细考虑下这整个委托与事件,事件的本质也就是对委托的一种使用。看我们事件注册绑定和多播委托的用法是一样的,事件的声明也是使用的委托类。
大家好好想想其中的奥妙,然后理解消化下。其实它们也没有那么难的。
下一节我们对委托和事件进行深入解析外加实际案例。