本文翻译整理自:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/events/how-to-publish-events-that-conform-to-net-framework-guidelines

以下的示例展示了怎样添加符合 .NET Framework 模式事件到自定义的类和结构体中。.NET Framework中所有的类库都是基于 EventHandler delegate,定义如下:

public delegate void EventHandler(object sender, EventArgs e);

尽管在类中定义的事件可以是任何有效的 delegate 类型,甚至 delegate 可以返回一个类型,但是通常建议事件以 .NET Framework 模式为准,基于 EventHandler

发布基于 EventHandler 模式的事件

  1. 如果需要传递额外的数据,就需要定义对于发布者和订阅者都需要的参数类,下面的类包含了一个额外的 message 字段,可以用来在发布者和订阅者之间传递信息,如下

    public class CustomEventArgs : EventArgs
    {
    public CustomEventArgs(string s)
    {
    msg = s;
    }
    private string msg;
    public string Message
    {
    get { return msg; }
    }
    }
  2. 在发布类中定义一个 delegate 类型,这里使用非泛型,定义 CustomEventHandler 类型,第一个参数是 object 类型,第二个参数是自定义的 CustomEventArgs 类型(用于传递自定义的数据) ,如下
    public delegate void CustomEventHandler(object sender, CustomEventArgs a); 
  3. 在发布类中,使用下面的一种方法声明事件

    第一种:如果不需要传递额外的数据,不需要自己定义 delegate 类型,在 System 命名空间中已经有预定义的事件类型 EventHandler ,直接使用即可:

    public event EventHandler RaiseCustomEvent;

    第二种:需要传递额外数据,使用非泛型版本,使用自己定义的 delegate 类型

    public event CustomEventHandler RaiseCustomEvent; 

    第三种:需要传递额外数据,使用泛型版本(.NET Framework 2.0 及以后版本可用)的 EventHandler

    public event EventHandler<CustomEventArgs> RaiseCustomEvent;  

  完整示例:

namespace DotNetEvents
{
using System;
using System.Collections.Generic; // 定义事件参数:包含一个额外的 message 字段
public class CustomEventArgs : EventArgs
{
public CustomEventArgs(string s)
{
message = s;
}
private string message; public string Message
{
get { return message; }
set { message = value; }
}
} // 发布者
class Publisher
{
// 使用 EventHandler<T> 声明事件
public event EventHandler<CustomEventArgs> RaiseCustomEvent; public void DoSomething()
{
// 可以在这里处理一些有用的事,然后触发事件
// 也可以在一些代码之前触发事件
OnRaiseCustomEvent(new CustomEventArgs("Did something"));
} // 把事件调用包含在一个 protected virtual 方法中,这样可以允许
// 子类重写事件调用
protected virtual void OnRaiseCustomEvent(CustomEventArgs e)
{
// 使用一个事件临时的引用,可以避免一种可能的竞争条件:
// 如果最后一个订阅者在 null 检查之后,事件触发之前突然
// 取消事件订阅
EventHandler<CustomEventArgs> handler = RaiseCustomEvent; // 如果没有订阅者,handler 将会是 null
if (handler != null)
{
// 格式化事件参数中的额外信息
e.Message += $" at {DateTime.Now}"; // 使用 () 操作符触发事件
handler(this, e);
}
}
} // 订阅者
class Subscriber
{
private string id;
public Subscriber(string ID, Publisher pub)
{
id = ID;
// 使用 C# 2.0 语法订阅事件
pub.RaiseCustomEvent += HandleCustomEvent;
} // 定义事件触发时要进行的操作
void HandleCustomEvent(object sender, CustomEventArgs e)
{
Console.WriteLine(id + " received this message: {0}", e.Message);
}
} class Program
{
static void Main(string[] args)
{
Publisher pub = new Publisher();
Subscriber sub1 = new Subscriber("sub1", pub);
Subscriber sub2 = new Subscriber("sub2", pub); // 调用触发事件的方法
pub.DoSomething(); // 保持控制台一直打开
Console.WriteLine("Press Enter to close this window.");
Console.ReadLine(); }
}
}

C#事件(Event): 发布符合 .NET Framework Guidelines 的事件的更多相关文章

  1. 事件Event一

    事件(Event)例如:最近的视觉中国'黑洞事件'.我们大多数人(订阅者)是通过XX平台(发布者)得知的这一消息,然后订阅者A出售视觉中国的股票(触发的方法),订阅者B买入视觉中国的股票. using ...

  2. 【温故知新】c#事件event

    从上一篇文章[温故知新]C#委托delegate可知,委托delegate和事件Event非常的相似,区别就是event关键字,给delegate穿上了个“马甲”. 让我们来看官方定义: 类或对象可以 ...

  3. 并发编程概述 委托(delegate) 事件(event) .net core 2.0 event bus 一个简单的基于内存事件总线实现 .net core 基于NPOI 的excel导出类,支持自定义导出哪些字段 基于Ace Admin 的菜单栏实现 第五节:SignalR大杂烩(与MVC融合、全局的几个配置、跨域的应用、C/S程序充当Client和Server)

    并发编程概述   前言 说实话,在我软件开发的头两年几乎不考虑并发编程,请求与响应把业务逻辑尽快完成一个星期的任务能两天完成绝不拖三天(剩下时间各种浪),根本不会考虑性能问题(能接受范围内).但随着工 ...

  4. C#事件(event)解析

    事件(event),这个词儿对于初学者来说,往往总是显得有些神秘,不易弄懂.而这些东西却往往又是编程中常用且非常重要的东西.大家都知道windows消息处理机制的重要,其实C#事件就是基于window ...

  5. Framework 类库的事件编程

    http://msdn.microsoft.com/zh-cn/library/aa663632.aspx 本页内容 EventHandler 委托 自定义的事件参数 参数化自定义事件 小结 本月的内 ...

  6. Event 发布与订阅(一)

    前言 主要讲的是发布与订阅在Event中的一个简单实现用来加深理解. C #中的事件(Event)的理解: 事件具有以下属性:(From Events) 发行者确定何时引发事件:订户确定对事件作出何种 ...

  7. C# 事件 event 【转】

    C#事件(event)解析   事件(event),这个词儿对于初学者来说,往往总是显得有些神秘,不易弄懂.而这些东西却往往又是编程中常用且非常重要的东西.大家都知道windows消息处理机制的重要, ...

  8. C# 事件 Event

    一.事件是什么 微软的定义:和委托类似,事件是后期绑定机制. 实际上,事件是建立在对委托的语言支持之上的.事件是对象用于(向系统中的所有相关组件)广播已发生事情的一种方式. 任何其他组件都可以订阅事件 ...

  9. 事件[event]_C#

    事件(event): 1.       事件是类在发生其关注的事情时用来提供通知的方式.例如,封装用户界面控件的类可以定义一个在单击该控件时发生的事件.控件类不关心单击按钮时发生了什么,但它需要告知派 ...

随机推荐

  1. 第三期 第三期 搜索——1.运动规划(motion_planing)

    运动规划的根本问题在于机器人可能存在于一个这样的世界中, 它可能想找到一条到达这个目标的路径,那么就需要指定一个到达那里的计划, 自动驾驶汽车也会遇到这个问题.他可能处于高速公路的附近的街道网络中,他 ...

  2. js如何获取地址栏上的参数id

    直接上js代码   方法1: 父页面跳转地址栏带id>>>>window.location.href='${ctxAdmin}/study/checkForm?id='+id+ ...

  3. 【原生JS】图片预加载之无序预加载

    图片预加载之无序预加载 <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset= ...

  4. [转]swagger2 入门教程

    swagger2 是一个规范和完整的框架,用于生成.描述.调用和可视化Restful风格的web服务,现在我们使用spring boot 整合它 作用: 1.接口的文档在线自动生成 2.功能测试 先介 ...

  5. [转载] iptables 防火墙设置

    http://hongwei.im/iptables-setting-for-ubuntu-1304/ Iptables是一个防火墙,所有的Ubuntu官方发行版(Ubuntu,Kubuntu,Xub ...

  6. P1104 最大公约数和最小公倍数问题

    题目描述 输入2个正整数 \(x0, y0 (2 \le x0 \lt 100000, 2 \le y0 \le 1000000)\) ,求出满足下列条件的 P,Q 的个数. 条件: P,Q是正整数 ...

  7. H3C 单路径网络中环路产生过程(2)

  8. 2019-8-31-AutoHotKey-用打码的快捷键

    title author date CreateTime categories AutoHotKey 用打码的快捷键 lindexi 2019-08-31 16:55:58 +0800 2019-06 ...

  9. vue移动端图片上传压缩

    上传压缩方法 import {api} from '../../api/api.js'; import axios from 'axios'; export function imgPreview ( ...

  10. hdu 6579 Operation (在线线性基)

    传送门 •题意 一个数组a有n个数 m个操作 操作① 询问$[l,r]$区间的异或值 操作② 在数组末尾追加一个数x,数组长度变为$n+1$ 其中$l,r$不直接给出,其中$l=l%n+1,r=r%n ...