かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

Reactive Extensions入門 5「イベントを監視する」

前回は、Observableクラスに定義されたメソッドをいくつか紹介しました。今回は、いよいよ実際に使いでのあるメソッドを紹介しようと思います。

今まで紹介したメソッドは、どちらかというと動作確認に使うのに適してると思います・・・。

さて、Reactive Extensionsは乱暴にいうとObserverパターンです。そして、.NETではObserverパターンはイベントで実現されています。ということはイベントをReactive ExtensionsのIObservableにすることも出来るはずです。そのような仕事をしてくれるのが、Observable.FromEventというメソッドです。

色々なオーバーライドがあるのですが、一番楽なのは文字列でイベント名を指定する方法です。早速見てみましょう。

// イベントのデリゲートとイベント引数
delegate void SampleEventHandler(object sender, SampleEventArgs e);
class SampleEventArgs : EventArgs
{
    public string Value { get; private set; }
    public SampleEventArgs (string value)
	{
        this.Value = value;
	}
}
// イベントを発行するだけのオブジェクト
class EventSource
{
    public event SampleEventHandler SampleEvent;
    public void OnSampleEvent(string value)
    {
        if (this.SampleEvent != null)
        {
            this.SampleEvent(this, new SampleEventArgs(value));
        }
    }
}

上記のクラスのSampleEventを監視して、イベントが発行されたらコンソールに値を出す処理をReactive Extensionsでやってみます。

var source = new EventSource();

// sourceのSampleEventを監視する
Observable.FromEvent<SampleEventArgs>(source, "SampleEvent")
    .Subscribe(e =>
        {
            // 適当に値出力
            Console.WriteLine("Raise Event");
            Console.WriteLine("  sender : " + e.Sender);
            Console.WriteLine("  value : " + e.EventArgs.Value);
        });

// イベントを発行する
source.OnSampleEvent("Hello");
source.OnSampleEvent("World");

実行結果は以下のようになります。

Raise Event
  sender : ConsoleApplication16.EventSource
  value : Hello
Raise Event
  sender : ConsoleApplication16.EventSource
  value : World

こんな感じです。因みにFromEventには以下のような書き方のバリエーションもあります。

Observable.FromEvent(
    (EventHandler<SampleEventArgs> h) => new SampleEventHandler(h),
    h => source.SampleEvent += h,
    h => source.SampleEvent -= h)

性能的には文字列指定じゃないほうがいいと思いますが・・・好みの問題だと思います。