本文翻译整理自: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(); }
}
}

最新文章

  1. 基于Python的函数回归算法验证
  2. [转]Modernizr的介绍和使用
  3. HTML基础 整理
  4. pymssql 安装测试
  5. Google Maps API 调用实例
  6. textarea在光标位置插入文字
  7. 编译boost python模块遇到的错误:../../libraries/boost_1_44_0/boost/python/detail/wrap_python.hpp:75:24: fatal error: patchlevel.h: No such file or directory
  8. linux学习(一个) 在unbuntu通过添加新的用户
  9. MySQL备份利器-xtrabackup的介绍和原理(附脑图)
  10. SpringMVC的工作流程以及组件说明
  11. Typora程序员的记事本.Typora常用快捷操作
  12. Django“少折腾”
  13. Vue导出json数据到Excel表格
  14. 使用jackson美化输出json/xml
  15. Date类型错误
  16. linux 除了某个文件或某个文件夹以外全部删除
  17. Mysql5.7主主互备安装配置
  18. XML & JSON---iOS-Apple苹果官方文档翻译
  19. 图片服务器(FastDFS)的搭建
  20. 白盒测试实践项目(day1)

热门文章

  1. H3C 网络号和主机号
  2. Java多线程遍历文件夹,广度遍历加多线程加深度遍历结合
  3. Java Annotation详解(二): 反射和Annotation
  4. 清除SVN未版控文件
  5. Python--day38---进程间通信--初识队列(multiprocess.Queue)
  6. 关于移动端弹层下的body滚动
  7. Vue组件中的父子传值
  8. vue-learning:12-vue获取模板内容的方式
  9. HDU 6623 Minimal Power of Prime(数学)
  10. 配置nutch