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 (续)

  《C# 知识回顾 - 事件入门


【参考】https://msdn.microsoft.com/zh-cn/library/w369ty8x(v=vs.80).aspx

【参考】微软官方文档

[.NET] C# 知识回顾 - Event 事件的更多相关文章

  1. C#基础知识回顾--委托事件

    在上一篇看到他我一下子就悟了(续)---委托,被人狂喷.说写的太空,没有什么内容之类的.所以准备在这里重写下,不过还是按着以前的方式尽量简单的写.这里我们以打篮球为例. 第一步:首先,其他对象订购事件 ...

  2. [C#] C# 知识回顾 - 你真的懂异常(Exception)吗?

    你真的懂异常(Exception)吗? 目录 异常介绍 异常的特点 怎样使用异常 处理异常的 try-catch-finally 捕获异常的 Catch 块 释放资源的 Finally 块 一.异常介 ...

  3. [C#] C# 知识回顾 - 学会处理异常

    学会处理异常 你可以使用 try 块来对你觉得可能会出现异常的代码进行分区. 其中,与之关联的 catch 块可用于处理任何异常情况. 一个包含代码的 finally 块,无论 try 块中是否在运行 ...

  4. [C#] C# 知识回顾 - 学会使用异常

    学会使用异常 在 C# 中,程序中在运行时出现的错误,会不断在程序中进行传播,这种机制称为“异常”. 异常通常由错误的代码引发,并由能够更正错误的代码进行 catch. 异常可由 .NET 的 CLR ...

  5. [C#] C# 知识回顾 - 异常介绍

    异常介绍 我们平时在写程序时,无意中(或技术不够),而导致程序运行时出现意外(或异常),对于这个问题, C# 有专门的异常处理程序. 异常处理所涉及到的关键字有 try.catch 和 finally ...

  6. C# 知识回顾 - 装箱与拆箱

    装箱与拆箱 目录 生活中的装箱与拆箱 C# 的装箱与拆箱 值类型和引用类型 装箱 拆箱 生活中的装箱与拆箱    我们习惯了在网上购物,这次你想买本编程书 -- <C 语言从入门到放弃> ...

  7. [C#] C# 知识回顾 - 装箱与拆箱

    装箱与拆箱 目录 生活中的装箱与拆箱 C# 的装箱与拆箱 值类型和引用类型 装箱 拆箱 读者见解 生活中的装箱与拆箱    我们习惯了在网上购物,这次你想买本编程书 -- <C 语言从入门到放弃 ...

  8. [C#] C# 知识回顾 - Lambda

    C# 知识回顾 - Lambda 序 它是第十一个希腊字母,一个拥有失意.无奈.孤独.低调等含义的流行符号,也指示一款称为“半条命”的游戏. 不过,这次我所讲的是 C# 中的 Lambda. 目录 L ...

  9. [.NET] C# 知识回顾 - 事件入门

    C# 知识回顾 - 事件入门 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6057301.html 序 之前通过<C# 知识回顾 - 委托 de ...

随机推荐

  1. javascript中的Array对象 —— 数组的合并、转换、迭代、排序、堆栈

    Array 是javascript中经常用到的数据类型.javascript 的数组其他语言中数组的最大的区别是其每个数组项都可以保存任何类型的数据.本文主要讨论javascript中数组的声明.转换 ...

  2. 对抗密码破解 —— Web 前端慢 Hash

    (更新:https://www.cnblogs.com/index-html/p/frontend_kdf.html ) 0x00 前言 天下武功,唯快不破.但在密码学中则不同.算法越快,越容易破. ...

  3. hibernate多对多关联映射

    关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...

  4. Power BI官方视频(3) Power BI Desktop 8月份更新功能概述

    Power BI Desktop 8月24日发布了更新版本.现将更新内容翻译整理如下,可以根据后面提供的链接下载最新版本使用. 1.主要功能更新 1.1 数据钻取支持在线版 以前的desktop中进行 ...

  5. Hawk 5. 数据库系统

    Hawk在设计之初,就是以弱schema风格定义的.没有严格的列名和列属性.用C#这样的静态强类型语言编写Hawk,其实并不方便.但弱schema让Hawk变得更灵活更强大. 因此,Hawk虽然之前支 ...

  6. RabbitMq应用一

    RabbitMq应用一 RabbitMQ的具体概念,百度百科一下,我这里说一下我的理解,如果有少或者不对的地方,欢迎纠正和补充. 一个项目架构,小的时候,一般都是传统的单一网站系统,或者项目,三层架构 ...

  7. 【绝对干货】仿微信QQ设置图形头像裁剪,让你的App从此炫起来~

    最近在做毕业设计,想有一个功能和QQ一样可以裁剪头像并设置圆形头像,额,这是设计狮的一种潮流. 而纵观现在主流的APP,只要有用户系统这个功能,这个需求一般都是在(bu)劫(de)难(bu)逃(xue ...

  8. Java开发中的23种设计模式详解

    [放弃了原文访问者模式的Demo,自己写了一个新使用场景的Demo,加上了自己的理解] [源码地址:https://github.com/leon66666/DesignPattern] 一.设计模式 ...

  9. background例子

  10. Android Fragment 剖析

    1.Fragment如何产生?2.什么是Fragment Android运行在各种各样的设备中,有小屏幕的手机,超大屏的平板甚至电视.针对屏幕尺寸的差距,很多情况下,都是先针对手机开发一套App,然后 ...