本文翻译整理自: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. SuperSocket接收过滤器工厂(ReceiveFilterFactory)

    接收过滤器工厂(ReceiveFilterFactory)用于为每个会话创建接收过滤器. 定义一个过滤器工厂(ReceiveFilterFactory)类型, 你必须实现接口 IReceiveFilt ...

  2. git之本地仓库关联远程仓库

    首先新建一个github respository 然后在自己本地新建一个maven项目,里面写点东西 如下图,将自己的项目所在地设置为本地git仓库 将本地仓库与远程关联,首先获取远程仓库的地址,点击 ...

  3. DOM事件和一些实用笔记

    let el = document.body.querySelector("style[type='text/css'], style:not([type])");返回HTML文档 ...

  4. H3C 虚拟模板方式配置PPP MP

  5. TP5单例模式操作Model

    tp5单例模式的代码实现 为什么要使用单例模式 使用单例模式实现逻辑处理与数据库操作分离能很大提升mysql的sql处理能力,并且易于维护 ArticleModel.php <?php name ...

  6. [转载] 使用StAX解析xml

    StAX 概述 从一开始,Java API for XML Processing (JAXP) 就提供了两种方法来处理 XML:文档对象模型(DOM)方法是用标准的对象模型表示 XML 文档:Simp ...

  7. Python--day32--复习:https和http的区别;黏包;黏包问题的解决方式;

    1,https和http的区别: https比较安全,传输的时候先对内容进行加密,收到后再进行解密:它的传输内容不容易拦截,就算拦截下来了,也是加密的,看不懂.但是要买证书,一年要好几万,小公司承担不 ...

  8. 【js】 vue 2.5.1 源码学习(十二)模板编译

    大体思路(十) 本节内容: 1. baseoptions 参数分析 2. options 参数分析 3. parse 编译器 4. parseHTNL 函数解析 // parse 解析 parser- ...

  9. P1002 Hello,World!

    题目描述 输出"Hello Wolrd!". 输入格式 无. 输出格式 输出一行"Hello World!". 样例输入 无. 样例输出 Hello World ...

  10. dotnet core 使用 CoreRT 将程序编译为 Native 程序

    现在微软有一个开源项目 CoreRT 能通过将托管的 .NET Core 编译为单个无依赖的 Native 程序 这个项目现在还没发布,但是能尝试使用,可以带来很多的性能提升 使用 CoreRT 发布 ...