Observable クラスは IObservable
まずは下準備。イベントを発生させるクラスを用意します。
public class GreetedEventArgs : EventArgs { public string Name { get; private set; } public GreetedEventArgs(string name) { Name = name; } } public class Greeting { public event EventHandler<GreetedEventArgs> Greeted; public void Greet(string name) { var h = Greeted; if (h != null) { h(this, new GreetedEventArgs(name)); } } }
イベントを IObservable
var g = new Greeting(); Observable.FromEvent<GreetedEventArgs>(g, "Greeted") .Subscribe(e => Console.WriteLine("Hello,{0}.", e.EventArgs.Name)); g.Greet("悟空"); // [実行結果] // Hello,悟飯.
この例の場合、イベントを発生させるオブジェクトとイベント名を渡すと、イベント引数を通知する IObservable
ただ、私はイベント名を文字列で指定するのが嫌。すごく嫌です。そんな型安全至上主義な人のために、タイプセーフな書き方も提供されています。
var g = new Greeting(); Observable.FromEvent<GreetedEventArgs>( h => g.Greeted += h, h => g.Greeted -= h) .Subscribe(e => Console.WriteLine("Hello,{0}.", e.EventArgs.Name)); g.Greet("ベジータ"); // [実行結果] // Hello,ベジータ.
イベントを IObservable
var g = new Greeting(); Observable.FromEvent<GreetedEventArgs>(g, "Greeted") .Where(e => e.EventArgs.Name == "フリーザ") .Subscribe(e => Console.WriteLine("Hello,{0}.", e.EventArgs.Name)); g.Greet("バーボン"); g.Greet("ドドリア"); g.Greet("フリーザ"); // [実行結果] // Hello,フリーザ.
もちろん、タイプセーフな書き方のときもイベントデータを操作できます。フィルタリングはさっきやったので、今度は Select で変換してみます。
var g = new Greeting(); Observable.FromEvent<GreetedEventArgs>( h => g.Greeted += h, h => g.Greeted -= h) .Select(e => { if (e.EventArgs.Name == "悟空") { return "カカロット"; } else { return e.EventArgs.Name; } }) .Subscribe(s => Console.WriteLine("Hello,{0}.", s)); g.Greet("悟空"); g.Greet("悟飯"); g.Greet("ベジータ"); // [実行結果] // Hello,カカロット. // Hello,悟飯. // Hello,ベジータ.
今回の試したのは Where と Select だけですが、使える拡張メソッドは大量にあります。いろいろ応用できそうです。もう、夢が広がりまくりんぐ。イベントも LINQ で処理する時代がきそうですね。