[.NET] C# 知识回顾 - Event 事件
C# 知识回顾 - Event 事件
【博主】反骨仔 【原文】http://www.cnblogs.com/liqingwen/p/6060297.html
序
昨天,通过《C# 知识回顾 - 事件入门》介绍了事件的定义及简单用法,今天我们通过控制台来看下“发布 - 订阅”的基本用法。
目录
一、发布基于 .NET 类库的事件
.NET类库中的所有事件均基于 EventHandler 委托,定义如下:
public delegate void EventHandler(object sender, EventArgs e);
你可以尝试手动输入 EventHandler ,然后按下“F12”跳转到定义:

.NET 2.0 引入了该委托的一个泛型版本,即 EventHandler<TEventArgs>。
【备注】虽然我们定义的事件可以基于任何自定的委托类型,但建议使用内置的 EventHandler 进行扩展。
二、采用 EventHandler 模式发布事件
1.这里选择继承了 BCL 中的类 EventArgs,可以在事件的触发时进行数据的传递。
class MyEventArgs : EventArgs
{
public string Message { get; private set; } public MyEventArgs(string message)
{
Message = message;
}
}
2.这里的第二个参数就是自定义的 MyEventArgs 类型,它继承了 EventArgs。
delegate void MyEventHandler(object sender, MyEventArgs args);
3.声明事件的几种形式:
(1)如果没有自定义 EventArgs 类,你可以直接使用 C# 中默认提供的非泛型 EventHandler 委托。
public event EventHandler MyEvent;
(2)如果使用的是非泛型的 EventHandler,并且写了一个自定义由 EventArgs 派生的类,可修改如下。
public event MyEventHandler MyEvent;
(3)如果使用的是高级的泛型版本,就不需要自定义委托。你只需要简单地将事件类型指定为 EventHandler<MyEventArgs>,将尖括号中的内容替换为自己的类的名称。
public event EventHandler<MyEventArgs> MyEvent;
三、一个简单的发布订阅 Demo
下面的示例通过将自定义的 MyEventArgs 类和 EventHandler<TEventArgs> 进行演示:
This is MyEventArgs.cs //事件参数
/// <summary>
/// 事件参数
/// </summary>
/// <remarks>一个自定义的类:自定义事件的参数</remarks>
class MyEventArgs : EventArgs
{
public string Message { get; } public MyEventArgs(string message)
{
Message = message;
}
}
This is Publisher.cs //发布者
/// <summary>
/// 事件发布者
/// </summary>
class Publisher
{
//声明一个泛型事件
public event EventHandler<MyEventArgs> MyEvent; public void Publish()
{
Console.WriteLine("Publis is starting"); //你可以在事件触发前写些代码 OnMyEvent(new MyEventArgs(DateTime.Now.ToString()));
} /// <summary>
/// 触发事件
/// </summary>
/// <param name="args"></param>
/// <remarks>虚方法,允许子类重写调用行为</remarks>
protected virtual void OnMyEvent(MyEventArgs args)
{
//只有在事件订阅时(!= null),才触发事件
MyEvent?.Invoke(this, args);
}
}
This is Subscriber.cs //订阅者
/// <summary>
/// 订阅者
/// </summary>
class Subscriber
{
public Guid Guid { get; } public Subscriber(Publisher publisher)
{
Guid = Guid.NewGuid();
//使用 C# 2 的语法进行订阅
publisher.MyEvent += Publisher_MyEvent;
} /// <summary>
/// 事件处理程序
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private void Publisher_MyEvent(object sender, MyEventArgs args)
{
Console.WriteLine($" Message is {args.Message}, Guid is {Guid}.");
}
}
This is Program.cs //控制台,用于启动
class Program
{
static void Main(string[] args)
{
var publisher = new Publisher();
var subscriber1 = new Subscriber(publisher);
var subscriber2 = new Subscriber(publisher); //触发事件
publisher.Publish(); Console.WriteLine("OK!");
Console.Read();
}
}

四、实现自定义事件访问器
事件一种是特殊类型的多播委托,只能从声明它的类中进行调用。这些方法需要预先通过事件访问器添加到委托的调用列表中,事件访问器跟我们平时使用的属性访问器,特殊的是他们的名字,事件访问器被命名为 add 和 remove。如果在代码中没有提供自定义的事件访问器,编译器会自动添加事件访问器。但在某些情况下,您可能需要提供自定义的行为。
class MyClass
{
/// <summary>
/// 锁
/// </summary>
private static object Locker = new object(); /// <summary>
/// 接口
/// </summary>
public interface IMyEvent
{
event EventHandler OnCall;
} public class MyEvent : IMyEvent
{
/// <summary>
/// 触发前事件
/// </summary>
event EventHandler PreEvent; public event EventHandler OnCall
{
add
{
lock (Locker)
{
PreEvent += value;
}
}
remove
{
lock (Locker)
{
PreEvent += value;
}
}
}
}
}
传送门
《C# 知识回顾 - 委托 delegate》、《C# 知识回顾 - 委托 delegate (续)》
【参考】https://msdn.microsoft.com/zh-cn/library/w369ty8x(v=vs.80).aspx
【参考】微软官方文档
[.NET] C# 知识回顾 - Event 事件的更多相关文章
- C#基础知识回顾--委托事件
在上一篇看到他我一下子就悟了(续)---委托,被人狂喷.说写的太空,没有什么内容之类的.所以准备在这里重写下,不过还是按着以前的方式尽量简单的写.这里我们以打篮球为例. 第一步:首先,其他对象订购事件 ...
- [C#] C# 知识回顾 - 你真的懂异常(Exception)吗?
你真的懂异常(Exception)吗? 目录 异常介绍 异常的特点 怎样使用异常 处理异常的 try-catch-finally 捕获异常的 Catch 块 释放资源的 Finally 块 一.异常介 ...
- [C#] C# 知识回顾 - 学会处理异常
学会处理异常 你可以使用 try 块来对你觉得可能会出现异常的代码进行分区. 其中,与之关联的 catch 块可用于处理任何异常情况. 一个包含代码的 finally 块,无论 try 块中是否在运行 ...
- [C#] C# 知识回顾 - 学会使用异常
学会使用异常 在 C# 中,程序中在运行时出现的错误,会不断在程序中进行传播,这种机制称为“异常”. 异常通常由错误的代码引发,并由能够更正错误的代码进行 catch. 异常可由 .NET 的 CLR ...
- [C#] C# 知识回顾 - 异常介绍
异常介绍 我们平时在写程序时,无意中(或技术不够),而导致程序运行时出现意外(或异常),对于这个问题, C# 有专门的异常处理程序. 异常处理所涉及到的关键字有 try.catch 和 finally ...
- C# 知识回顾 - 装箱与拆箱
装箱与拆箱 目录 生活中的装箱与拆箱 C# 的装箱与拆箱 值类型和引用类型 装箱 拆箱 生活中的装箱与拆箱 我们习惯了在网上购物,这次你想买本编程书 -- <C 语言从入门到放弃> ...
- [C#] C# 知识回顾 - 装箱与拆箱
装箱与拆箱 目录 生活中的装箱与拆箱 C# 的装箱与拆箱 值类型和引用类型 装箱 拆箱 读者见解 生活中的装箱与拆箱 我们习惯了在网上购物,这次你想买本编程书 -- <C 语言从入门到放弃 ...
- [C#] C# 知识回顾 - Lambda
C# 知识回顾 - Lambda 序 它是第十一个希腊字母,一个拥有失意.无奈.孤独.低调等含义的流行符号,也指示一款称为“半条命”的游戏. 不过,这次我所讲的是 C# 中的 Lambda. 目录 L ...
- [.NET] C# 知识回顾 - 事件入门
C# 知识回顾 - 事件入门 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6057301.html 序 之前通过<C# 知识回顾 - 委托 de ...
随机推荐
- web全栈开发之网站开发二(弹出式登录注册框前端实现-类腾讯)
这次给大家分享的是目前很多网站中流行的弹出式登录框,如下面的腾讯网登录界面,采用弹出式登录的好处是大大提升了网站的用户体验和交互性,用户不用重新跳转到指定的页面就能登录,非常方便 先来个演示地址 要实 ...
- Linux 添加新磁盘,在线扩充空间
CentOS 7开发环境中的home 目录空间满了,需要增加空间 到虚拟机上执行"ls /sys/class/scsi_host",然后重新扫描SCSI总线来添加设备.如右图.然后 ...
- 【开源】.net 分布式架构之监控平台
开源地址:http://git.oschina.net/chejiangyi/Dyd.BaseService.Monitor .net 简单监控平台,用于集群的性能监控,应用耗时监控管理,统一日志管理 ...
- 掌握javascript中的最基础数据结构-----数组
这是一篇<数据结构与算法javascript描述>的读书笔记.主要梳理了关于数组的知识.部分内容及源码来自原作. 书中第一章介绍了如何配置javascript运行环境:javascript ...
- EntityFramework.Extended 支持 MySql
EntityFramework.Extended 默认不支持 MySql,需要配置如下代码: [DbConfigurationType(typeof(DbContextConfiguration))] ...
- OEL上使用yum install oracle-validated 简化主机配置工作
环境:OEL 5.7 + Oracle 10.2.0.5 RAC 如果你正在用OEL(Oracle Enterprise Linux)系统部署Oracle,那么可以使用yum安装oracle-vali ...
- java单向加密算法小结(2)--MD5哈希算法
上一篇文章整理了Base64算法的相关知识,严格来说,Base64只能算是一种编码方式而非加密算法,这一篇要说的MD5,其实也不算是加密算法,而是一种哈希算法,即将目标文本转化为固定长度,不可逆的字符 ...
- node.js学习(二)--Node.js控制台(REPL)&&Node.js的基础和语法
1.1.2 Node.js控制台(REPL) Node.js也有自己的虚拟的运行环境:REPL. 我们可以使用它来执行任何的Node.js或者javascript代码.还可以引入模块和使用文件系统. ...
- C# 对象实例化 用json保存 泛型类 可以很方便的保存程序设置
用于永久化对象,什么程序都行,依赖NewtonSoft.用于json序列化和反序列化. using Newtonsoft.Json; using System; using System.Collec ...
- python性能检测工具整理
python 运行后出现core dump产生core.**文件,可通过gdb来调试 Using GDB with a core dump having found build/python/core ...