[.NET] C# 知识回顾 - Event 事件

时间:2022-11-25 17:57:05

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] C# 知识回顾 - Event 事件

  .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();
}
}

[.NET] C# 知识回顾 - Event 事件

四、实现自定义事件访问器

  事件一种是特殊类型的多播委托,只能从声明它的类中进行调用。这些方法需要预先通过事件访问器添加到委托的调用列表中,事件访问器跟我们平时使用的属性访问器,特殊的是他们的名字,事件访问器被命名为 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

【参考】微软官方文档