ReactivePropertyのメジャー機能以外の紹介と使いどころ考察


はじめに

いつもお世話になっているReactivePropertyなんですけど、使い方を習熟するべく元のソースを見ていたら結構知らない機能があったため、勉強がてら投稿させていただきます。


機能確認用プロジェクト

ReactivePropertySample(github)


環境

ReactiveProperty: 5.1.1 (2018/06/21)

Prism: 6.3.0 (2017/03/25)

.NET Framework: 4.7.2


機能


ReactivePropertySlimReadOnlyReactivePropertySlim


  • 参考

    ReactivePropertySlim詳解

    ReactiveProperty v4.1.0 をリリースしました



  • 機能説明

    軽量なReactivePropertyだそうです。ReactivePropertyとの違いがReactivePropertySlim詳解に書かれているので引用させていただきます。


    フィールド数を最小限にしてアロケーションを抑えた(無印はバリデーション系などのためにSubjectやLazyの保持がかなりある)

    内部で使ってるSubjectをやめて完全自前管理&Subscription(IDisposable)自体を連結リストのノード自身にすることで、複数Subscribeでのアロケーションをなくした

    変更通知の実行をスケジューラー経由で行わず直接する(無印はデフォルトでDispatcher経由になるけれど、パフォーマンス上の問題と、厄介な挙動を時折示していた)

    バリデーション系のメソッドを除去

    ReactivePropertySlimからObservable Sourceを受けとる機能/コンストラクタを削除(ReadOnlyReactivePropertySlimのみがその機能を持つ)




上記の内容に反しない限り置き換えちゃっても大丈夫な気がしてます。例えば私はMVVMのModelでもReactivePropertyを使用しているのですがスケジューラ―関係やバリデーションは使っていなかったので今後はReactivePropertySlimを使用していこうかと思いました。

後はToReadOnlyReactivePropertyしていたところはToReadOnlyReactivePropertySlimに置き換えるとか。


  • 機能確認用

ReactivePropertySlim


AsyncReactiveCommand


Subscribeメソッドが非同期メソッドを受け取って、その非同期メソッドが実行中の間は自動的にCanExecuteをFalseにしてくれるというCommandです。


一度ボタンを押したら処理が終わるまでそのボタンの二度押しをできないようにできるみたいです。似たような機能に後述するBusyNotifierがありました。


  • 機能確認用

AsyncReactiveCommand


ReactiveTimer


機能は、Observable.TimerのStop/Start出来る版です。


より便利なTimerなようなのでReactivePropertyを使用しているならばこちらを使用したほうが良さそうです。


  • 機能確認用

ReactiveTimer


BooleanNotifier

BooleanNotifier


BusyNotifier


  • 参考

ReactivePropertyで2度押し防止/ReactiveProperty v2.7.0をリリースしました


  • 機能説明

ProcessStartを実行するとtrueになり、ProcessStartの戻り値であるIDisposableをDisposeするとfalseになります。

コードで書くと

            using (this.BusyNotifier.ProcessStart())

{
await 重い処理Async();
}

となります。この処理をReactiveCommandのSubscribeに書いてそのコマンドの生成を

var command = this.BusyNotifier.Select(b => !b).ToReactiveCommand()

とすれば二度押しを抑止することができます。ボタンひとつひとつを制御したい場合はAsyncReactiveCommandが有効ですが、一つボタンを押されれば全てのボタンを抑止したいときなどはBusyNotifierのほうが良さげに感じました。

もうひとつの特徴として、処理を並列で実行した場合に、全ての処理でDisposeされるまでBusyNotifierはfalseを維持し続けてくれました。自分のイメージだとTask.WhenAllの戻り値なし版みたいな感じです。それぞれの処理の戻り値には興味なくて、ただ単に非同期処理が終わったことだけが知りたい場合には有効な気がしました。(例えば画面に表示する情報を全部取得し終わってから操作可能にしたいときとか)


  • 機能確認用

BusyNotifier


CountNotifier


インクリメントとデクリメントを行うクラスです。コンストラクタでインクリメント出来る最大値を指定することもできます。IObservableとして使うことができます。CountChangedStatusはIncrementなのかDecrementなのかEmpty(0になった)のかを表すenumです。

Incrementは、IDisposableを返します。これをDisposeすることで、Incrementを取り消すこともできます。IncrementとDecrementは、引数に数値を渡すことで像現地を指定することができます。


単純にカウンターしても使用できそうですし、CountChangedStatusを監視していればIncrementからDecrementに変化したときだけ(逆もまた然り)を検出できそうです。


  • 機能確認用

CountNotifier


MessageBroker


  • 参考

ReactiveProperty v2.7.4をリリースしました


  • 機能説明

Messengerパターンを実現できます。PrismのEventAggregatorでも同じことが実現できました。MessageBrokerのほうは購読後すぐにRxにつなげたりできます。あと呼び出しがシングルトンでした。


  • 機能確認用

MessageBroker


ScheduledNotifier


  • 参考

ReactivePropertyのNotifier系クラス

ReactiveProperty : WPF/SL/WP7のためのRxとMVVMを繋ぐ拡張ライブラリ


  • 機能説明

SubjectISchedulerを合わせたような機能です。OnNextを任意の時間後に発行できます。あとIProgressも実装しているので進捗専用ならSubjectよりこれを使ったほうが良さそうです。


  • 機能確認用

ScheduledNotifier


Pairwise

たまに前後値を比較したいときがあるので重宝しています。ひとつskipした同じものをzipして~というのは解っている人がみればわかるんでしょうけどもぱっとみ意図が解りづらいので、Pairwiseという名前を付けてくれたのは共通認識の点で助かります。


  • 機能確認用

Pairwise


ReactivePropertyMode


  • 参考

MVVMをリアクティブプログラミングで快適にReactivePropertyオーバービュー

ReactiveProperty v5.1.1 をリリースしました


  • 機能説明

ReactivePropertyReactivePropertySlimを初期化するときにReactivePropertyModeを指定することで挙動を変更することができます。

ReactivePropertyMode

要素
説明

None
指定なし

DistinctUntilChanged
この要素を追加すると、同じ値がきたら発火しない。どんな値でも漏らさず流したいなら外した方が良い

RaiseLatestValueOnSubscribe
Subscribeしたときの最初の一回を実行するか否かを指定できる。設定だけして今までのは流したくないなら外した方が良い

IgnoreInitialValidationError
SetValidateNotifyError等を設定しておいて最初の一回目のエラーは無視したい場合には追加した方が良い(例えば空の入力を許さないTextBoxだけど画面表示時はエラー表示を出したくないとか)

Default
DistinctUntilChanged と RaiseLatestValueOnSubscribe


  • 機能確認用

ReactivePropertyMode