【Rx】Observable.FromEventを見てみる【C#】

はじめに

最近は高校総体があり、テストがあり、結構忙しかったのです。
今はテストも終わり、やりたいことがやっとできるようになったので少しホッとしてます。

最近は、趣味で UniRx のソースを読んだりしています。
内部挙動がよく分かるのでソースコードを読んで内部実装を知るのはとてもいいことですね :)

さて、今回は Observable.FromEvent の使い方について簡単にメモを残したいと思います。
初めてみたときによくわからなかったので、自分なりに分かりやすく使い方を解説してみました。

event構文とオブザーバーパターン

C#は言語仕様に event を持っていますが、これはイベント発生元が 観測対象 (Observable) で、イベントハンドラが 観測者 (Observer) とみなすと、オブザーバーパターン を実現していると分かりますね。
つまり、言語仕様の event はうまくやれば IObservable<T> に変換することができます。

Observable.FromEventメソッド

さて、eventIObservable<T> に変換するメソッドを紹介します。

IObservable<TEventArgs> FromEvent<TEventHandler, TEventArgs>(
Func<Action<TEventArgs>, TEventHandler> conversion,
Action<TEventHandler> addHandler,
Action<TEventHandler> removeHandler)

このメソッドは他にもオーバーロードが用意されていますが、よく使うのはこのシグネチャでしょう。

1つ目の型引数には イベントハンドラの型 を指定し、2つ目の型引数には 観測値の型 を指定します。
第一引数にはOnNextを発行させるデリゲート (イベントハンドラにあたる) を指定し、第二引数、第三引数にはイベントハンドラを登録・解除する処理を行うデリゲートを渡します。

言葉では説明しにくいので例を見てみましょう。

例: EventHandlerをIObservable<T>に変換する

こんな感じになります。

using System;
using System.Reactive.Linq;

namespace aridai
{
    public static class Program
    {
        //  EventHandlerデリゲートのシグネチャは
        //  delegate void EventHandler(object sender, EventArgs e);
        //  第一引数にobject型
        //  第二引数にEventArgs型
        //  戻り値がvoid型

        public static event EventHandler MyEvent;

        public static IObservable<EventArgs> MyEventAsObservable { get; private set; }

        public static void Main()
        {
            MyEventAsObservable =
                Observable.FromEvent<EventHandler, EventArgs>(
                onNext => (sender, args) => onNext(args),
                handler => MyEvent += handler,
                handler => MyEvent -= handler);
        }

        private static void MyHandler(object sender, EventArgs args)
        {
            //  やっていることは
            //  イベントにイベントハンドラを登録して
            //  そのイベントハンドラ内で
            //  OnNextを呼び出している

            //  ラムダ式で書くことで
            //  OnNextの参照をキャプチャすることができる

            //  OnNext(args);
            //  ↑こういうこと
        }
    }
}

ラムダ式の中でラムダ式を書いているので分かりにくいかもしれませんが、
分解して考えてみるとそんなに難しいことはしていません。

さいごに

今回は簡単に Observable.FromEvent の使い方を説明しましたが、他にもリフレクションを利用したバージョンや Observable.FromEvetnPattern というのもあるので調べてみると良いでしょう。
意見などがあれば気軽にコメントしてください :)

2017/06/15 14:38:57
コメントを投稿する