Reactive Extensions (Rx) 入门(4) —— Rx的事件编程②
原文:http://www.atmarkit.co.jp/fdotnet/introrx/introrx_01/introrx_02_02.html
作者:河合 宜文
事件是什么?用Rx来处理事件的优势
让我们来看看如何用Rx特有的事件Obserable转换事件处理的。在这之前,让我们考虑一下事件在.NET中的应用场景。
最具有代表性的应该是GUI的事件了。比如:按钮点击,鼠标移动等,这些全是通过事件来处理的。而WindowsPhone(简记为WP7)中增加的比如触摸等手势输入都是事件处理,TabletPC和WP7一样,也配备了传感器,还有最近出尽风头的Kinect设备,也配置了传感器。
另外,还有以通知(推送)为目的,例如INotifyPropertyChanged接口就是利用事件来通知属性发生变化了。还有FileSystemWatcher类是对文件或者文件夹进行变化监视通过事件进行通知。其他还有Timer的事件,WebClient的异步方法等也是利用了事件来处理。
GUI事件:合成
那么用Rx来操作事件有什么爽的呢?如果要说的话,首先是可以“合成”。比如:GUI事件中的鼠标按下/移动/放开 想要对这组操作进行组合的场景,一般的作法都是外部做一个Flag来管理,这样可能会使得代码变得复杂且可读性下降,而且除了这种组合之外,再想在按下/移动/放开事件中处理一些别的,则非常容易使原有代码结构发生破坏。
但如果使用Rx来操作那么则无需使用外部的Flag,直接可以将按下/移动/放开合成为一个新的事件。这样的话,即不用Flag来控制也可以在按下/移动/放开里各自处理事件。代码也不会混在一起,更加简洁。另外,合成的事件可读性也被大大提高了。
下面的代码示例如何将 按下/移动/放开 合成一个新的事件并进行处理:
UnitTest
Rx的特点是可以自由的处理事件,利用Rx可以解决本来很困难的事件的UnitTest。例如:3分30秒时生成一个数值"10",之后的4分0秒时生成一个数值"20",Rx能模拟这样的时间和值组合的事件。这些测试用的方法都在Microsoft.Reactive.Testing 程序集里(用NuGet "Rx-Testing")。关于Rx的UnitTest,将在后面再详细介绍。
FromEvent方法和FromEventPattern方法
用Rx处理事件,需要用 FromEvent 方法或者 FromEventPattern 方法将事件变为 IObservable<T> 对象。FromEvent 方法可以转换 Action<T> 代理,序列元素则为 T 。FromEventPattern 方法可以转换 EventHandler 代理,序列元素则为 EventPattern<TEventArgs>,它包装了 Object 类型的 sender 和 TEventArgs 类型的 e。
事件的Rx变换:指定事件名
先来看看 FromEventPattern 方法。
button1.ClickAsObservable().Select(ev => new { Sender = button1, EventArgs = ev })
接下来会进一步介绍 Rx 如何进行合成的。