Rx 提供工厂方法,使你能够与 .NET 中的现有异步源进行桥接,以便你可以在任何类型的数据流上使用 Rx 提供的丰富组合、筛选和资源管理功能。 本主题介绍 FromEventPattern 运算符,该运算符允许将 .NET 事件作为可观察序列“导入”到 Rx 中。 每次引发事件时,OnNext 消息都将传递到可观测序列。 然后,可以像处理任何其他可观察序列一样操作事件数据。
Rx 不旨在替换现有的异步编程模型,例如 .NET 事件、异步模式或任务并行库。 但是,当你尝试撰写事件时,Rx 的工厂方法将为你提供在当前编程模型中找不到的便利。 这尤其适用于资源维护 (例如何时取消订阅) 和筛选 (例如选择要接收) 的数据类型。 在本主题和后续内容中,你可以了解这些 Rx 功能如何帮助你进行异步编程。
将 .NET 事件转换为 Rx 可观测序列
下面的示例为鼠标移动事件创建一个简单的 .NET 事件处理程序,并在 Windows 窗体上的标签中输出鼠标的位置。
using System.Linq;
using System.Windows.Forms;
using System.Reactive;
using System.Reactive.Linq;
using System;
using WinForm;
using System.Reactive.Disposables;
class Program {
 
    static void Main() 
    {
         var lbl = new Label(); 
         var frm = new Form { Controls = { lbl } }; 
         frm.MouseMove += (sender, args) =>
         {
              lbl.Text = args.Location.ToString();
         };
         Application.Run(frm);
    }; 
}
若要将事件导入 Rx,可以使用 FromEventPattern 运算符,并提供将由桥接的事件引发的 EventArgs 对象。 FromEventPattern 运算符处理采用对象发送方和一些 EventArgs 的事件,并使用反射查找这些添加/删除方法。 然后,它将给定事件转换为具有 EventPattern 类型的可观测序列,该类型捕获发送方和事件参数。
对于具有一个参数 (非标准事件) 的委托,可以使用 FromEvent 运算符,该运算符采用一对用于附加和分离处理程序的函数。
在以下示例中,我们将 Windows 窗体的鼠标移动事件流转换为可观察序列。 每次触发鼠标移动事件时,订阅者都将收到 OnNext 通知。 然后,我们可以检查此类通知的 EventArgs 值,并获取鼠标移动的位置。
using System.Linq;
using System.Windows.Forms;
using System.Reactive;
using System.Reactive.Linq;
using System;
using WinForm;
using System.Reactive.Disposables;
class Program {
 
    static void Main() 
    {
         var lbl = new Label(); 
         var frm = new Form { Controls = { lbl } }; 
         IObservable<EventPattern<MouseEventArgs>> move = Observable.FromEventPattern<MouseEventArgs>(frm, "MouseMove");
         move.Subscribe(evt => { 
                             lbl.Text = evt.EventArgs.Location.ToString(); 
                       }) ;
         Application.Run(frm);
   }; 
}
请注意,在此示例中, move 成为一个可观察的序列,我们可以在此序列中进一步操作。 
              使用 LINQ 运算符查询可观测序列主题将介绍如何将此序列投影到 Points 类型的集合中并筛选其内容,以便应用程序仅接收满足特定条件的值。
事件处理程序的清理由 Subscribe 方法返回的 IDisposable 对象处理。 调用 Dispose (到达此示例中 using 块的末尾来完成) 将释放序列使用的所有资源,包括基础事件处理程序。 这基本上负责代表你取消订阅事件。