本文翻译整理自: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. H3C ICMP

  2. 请求(RequestInfo)

    请求类型 StringRequestInfo 用在 SuperSocket 命令行协议中. 你也可以根据你的应用程序的需要来定义你自己的请求类型. 例如, 如果所有请求都包含 DeviceID 信息, ...

  3. H3C MAC地址

  4. Beta版是什么意思

    外部测试版的意思. 软件会出现三种版本 1.alpha内部测试版本,极不稳定,一般也不会出现的公众视线,仅供内部测试人员测试用. 2.beta公共测试版,就是对外发布软件的测试版,收集公众的意见和建议 ...

  5. H3C 以跳数评估的路由并非最优路径

  6. H3C 动态路由协议的基本原理

  7. H3C DHCP服务器基本配置示例

  8. java用普通类如何实现枚举功能

    用普通类如何实现枚举功能,定义一个Weekday的类来模拟枚举功能.     1.私有的构造方法.     2.每个元素分别用一个公有的静态成员变量表示.      可以有若干公有方法或抽象方法.采用 ...

  9. vuex 快速上手,具体使用方法总结(含使用例子)

    网上有关vuex的文章很多,但有些比较复杂,这篇文章能让你快速使用vuex: vuex 用处:管理全局状态(类似全局变量,每个组件都能访问到) vuex 用法: //下面是一个js文件,用最简单最全的 ...

  10. linux 存取 I/O 内存

    在一些平台上, 你可能逃过作为一个指针使用 ioremap 的返回值的惩罚. 这样的使用不 是可移植的, 并且, 更加地, 内核开发者已经努力来消除任何这样的使用. 使用 I/O 内 存的正确方式是通 ...