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

# はじめに
いつもお世話になっている[ReactiveProperty](https://github.com/runceel/ReactiveProperty)なんですけど、使い方を習熟するべく元のソースを見ていたら結構知らない機能があったため、勉強がてら投稿させていただきます。

# 機能確認用プロジェクト
[ReactivePropertySample(github)](https://github.com/kwhrkzk/ReactivePropertySample/tree/master/ReactivePropertySample)

# 環境
ReactiveProperty: 5.1.1 (2018/06/21)
Prism: 6.3.0 (2017/03/25)
.NET Framework: 4.7.2

# 機能
## [ReactivePropertySlim][]と[ReadOnlyReactivePropertySlim](https://github.com/runceel/ReactiveProperty/blob/master/Source/ReactiveProperty.NETStandard/ReactivePropertySlim.cs)
- 参考
[ReactivePropertySlim詳解][]
[ReactiveProperty v4.1.0 をリリースしました](https://blog.okazuki.jp/entry/2018/01/18/103347)

- 機能説明
軽量な[ReactiveProperty][]だそうです。[ReactiveProperty][]との違いが[ReactivePropertySlim詳解][]に書かれているので引用させていただきます。
> フィールド数を最小限にしてアロケーションを抑えた（無印はバリデーション系などのためにSubjectやLazyの保持がかなりある）
> 内部で使ってるSubjectをやめて完全自前管理＆Subscription(IDisposable)自体を連結リストのノード自身にすることで、複数Subscribeでのアロケーションをなくした
> 変更通知の実行をスケジューラー経由で行わず直接する（無印はデフォルトでDispatcher経由になるけれど、パフォーマンス上の問題と、厄介な挙動を時折示していた）
> バリデーション系のメソッドを除去
> ReactivePropertySlimからObservable Sourceを受けとる機能/コンストラクタを削除（ReadOnlyReactivePropertySlimのみがその機能を持つ）

上記の内容に反しない限り置き換えちゃっても大丈夫な気がしてます。例えば私はMVVMのModelでも[ReactiveProperty][]を使用しているのですがスケジューラ―関係やバリデーションは使っていなかったので今後は[ReactivePropertySlim][]を使用していこうかと思いました。
後は[ToReadOnlyReactiveProperty](https://github.com/runceel/ReactiveProperty/blob/master/Source/ReactiveProperty.NETStandard/ReactivePropertySlim.cs)していたところは[ToReadOnlyReactivePropertySlim](https://github.com/runceel/ReactiveProperty/blob/master/Source/ReactiveProperty.NETStandard/ReadOnlyReactiveProperty.cs)に置き換えるとか。

- 機能確認用

[ReactivePropertySlim](https://github.com/kwhrkzk/ReactivePropertySample/tree/master/ReactivePropertySample/ViewModule/ReactivePropertySlim)

## [AsyncReactiveCommand][]
- 参考
[AsyncReactiveCommandでWPFのお手軽ダブルクリック抑制](https://qiita.com/soi/items/eca0601ad0fc4e401623)
[ReactiveProperty v2.9.0とv3.0.0-pre5をリリースしました。][]

- 機能説明
[ReactiveProperty v2.9.0とv3.0.0-pre5をリリースしました。][]から引用させていただきます。

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

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

- 機能確認用

[AsyncReactiveCommand](https://github.com/kwhrkzk/ReactivePropertySample/blob/master/ReactivePropertySample/ViewModule/ScheduledNotifier/ViewModels/ScheduledNotifierViewModel.cs)


## [ReactiveTimer](https://github.com/runceel/ReactiveProperty/blob/master/Source/ReactiveProperty.NETStandard/ReactiveTimer.cs)
- 参考
[MVVMとリアクティブプログラミングを支援するライブラリ「ReactiveProperty v2.0」オーバービュー](https://blog.okazuki.jp/entry/2015/02/22/212827)
[ReactiveProperty ver 0.3.0.0 - MとVMのバインディングという捉え方][]

- 機能説明
[ReactiveProperty ver 0.3.0.0 - MとVMのバインディングという捉え方][]から引用させていただきます。

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

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

- 機能確認用

[ReactiveTimer](https://github.com/kwhrkzk/ReactivePropertySample/tree/master/ReactivePropertySample/ViewModule/ReactiveTimer)

## [BooleanNotifier][]

- 参考
[ReactiveProperty ver 0.3.0.0 - MとVMのバインディングという捉え方][]
[ReactivePropertyのNotifier系クラス][]

- 機能説明
bool値を制御する機能で[TurnOn][BooleanNotifier]や[TurnOff][BooleanNotifier]、[SwitchValue][BooleanNotifier]が特徴的です。[TurnOn][BooleanNotifier]や[TurnOff][BooleanNotifier]を使用すると値の変化時だけ通知することができます。[Value][BooleanNotifier]で直接値を設定することもできますが[Value][BooleanNotifier]の場合は同じ値を設定しても通知が飛んでしまいます。true-falseの変化時だけ通知が欲しいときなどに使えそうです。
[SwitchValue][BooleanNotifier]はtrueとfalseが交互に切り替わるのでトグルボタンを作るときに使えそうです。

[BooleanNotifier]:https://github.com/runceel/ReactiveProperty/blob/master/Source/ReactiveProperty.NETStandard/Notifiers/BooleanNotifier.cs

- 機能確認用

[BooleanNotifier](https://github.com/kwhrkzk/ReactivePropertySample/tree/master/ReactivePropertySample/ViewModule/BooleanNotifier)


## [BusyNotifier][]
- 参考

[ReactivePropertyで2度押し防止/ReactiveProperty v2.7.0をリリースしました](https://blog.okazuki.jp/entry/2016/04/09/005825)

- 機能説明

[ProcessStart][BusyNotifier]を実行するとtrueになり、[ProcessStart][BusyNotifier]の戻り値である[IDisposable](https://msdn.microsoft.com/ja-jp/library/system.idisposable(v=vs.110).aspx)をDisposeするとfalseになります。
コードで書くと

```csharp
            using (this.BusyNotifier.ProcessStart())
            {
                await 重い処理Async();
            }

```

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

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

とすれば二度押しを抑止することができます。ボタンひとつひとつを制御したい場合は[AsyncReactiveCommand][]が有効ですが、一つボタンを押されれば全てのボタンを抑止したいときなどは[BusyNotifier][]のほうが良さげに感じました。
もうひとつの特徴として、処理を並列で実行した場合に、全ての処理でDisposeされるまで[BusyNotifier][]はfalseを維持し続けてくれました。自分のイメージだと[Task.WhenAll](https://msdn.microsoft.com/ja-jp/library/hh160374(v=vs.110).aspx)の戻り値なし版みたいな感じです。それぞれの処理の戻り値には興味なくて、ただ単に非同期処理が終わったことだけが知りたい場合には有効な気がしました。(例えば画面に表示する情報を全部取得し終わってから操作可能にしたいときとか)

- 機能確認用
 
[BusyNotifier](https://github.com/kwhrkzk/ReactivePropertySample/tree/master/ReactivePropertySample/ViewModule/BusyNotifier)

## [CountNotifier](https://github.com/runceel/ReactiveProperty/blob/master/Source/ReactiveProperty.NETStandard/Notifiers/CountNotifier.cs)

- 参考
[ReactiveProperty ver 0.3.0.0 - MとVMのバインディングという捉え方][]
[ReactivePropertyのNotifier系クラス][]

- 機能説明
[ReactivePropertyのNotifier系クラス][]から引用させていただきます。

> インクリメントとデクリメントを行うクラスです。コンストラクタでインクリメント出来る最大値を指定することもできます。IObservable<CountChangedStatus>として使うことができます。CountChangedStatusはIncrementなのかDecrementなのかEmpty(0になった）のかを表すenumです。
> Incrementは、IDisposableを返します。これをDisposeすることで、Incrementを取り消すこともできます。IncrementとDecrementは、引数に数値を渡すことで像現地を指定することができます。

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

- 機能確認用

[CountNotifier](https://github.com/kwhrkzk/ReactivePropertySample/tree/master/ReactivePropertySample/ViewModule/CountNotifier)

## [MessageBroker][]
- 参考

[ReactiveProperty v2.7.4をリリースしました](https://blog.okazuki.jp/entry/2016/06/24/222331)

- 機能説明

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

- 機能確認用

[MessageBroker](https://github.com/kwhrkzk/ReactivePropertySample/tree/master/ReactivePropertySample/ViewModule/MessageBroker)

[MessageBroker]:https://github.com/runceel/ReactiveProperty/blob/master/Source/ReactiveProperty.NETStandard/Notifiers/MessageBroker.cs
[EventAggregator]:https://github.com/runceel/PrismEdu/tree/master/07.EventAggregator



## [ScheduledNotifier][]
- 参考

[ReactivePropertyのNotifier系クラス][]
[ReactiveProperty : WPF/SL/WP7のためのRxとMVVMを繋ぐ拡張ライブラリ][]

- 機能説明

[Subject][]に[IScheduler](https://github.com/dotnet/reactive/blob/f94b0062606c1f69be5c56594e016110c68f6209/Rx.NET/Source/src/System.Reactive/Concurrency/IScheduler.cs)を合わせたような機能です。OnNextを任意の時間後に発行できます。あと[IProgress][]も実装しているので進捗専用なら[Subject][]よりこれを使ったほうが良さそうです。


[Subject]:https://github.com/dotnet/reactive/blob/master/Rx.NET/Source/src/System.Reactive/Subjects/Subject.cs
[IProgress]:https://msdn.microsoft.com/ja-jp/library/hh138298(v=vs.110).aspx
[ScheduledNotifier]:https://github.com/runceel/ReactiveProperty/blob/master/Source/ReactiveProperty.NETStandard/Notifiers/ScheduledNotifier.cs

- 機能確認用

[ScheduledNotifier](https://github.com/kwhrkzk/ReactivePropertySample/tree/master/ReactivePropertySample/ViewModule/ScheduledNotifier)

## [Pairwise][]
- 参考
[MVVMをリアクティブプログラミングで快適にReactivePropertyオーバービュー][]

- 機能説明
[MVVMをリアクティブプログラミングで快適にReactivePropertyオーバービュー][]からまんま引用させていただきます。
> 以下のショートカットです。
> ox.Zip(ox.Skip(1), (x, y) => new OldNewPair<T>(x, y))
> OldNewPair型はOldItem, NewItemで値にアクセスできます。

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

- 機能確認用

[Pairwise](https://github.com/kwhrkzk/ReactivePropertySample/blob/master/ReactivePropertySample/ViewModule/Pairwise/ViewModels/PairwiseViewModel.cs)

## [ReactivePropertyMode][]
- 参考

[MVVMをリアクティブプログラミングで快適にReactivePropertyオーバービュー][]
[ReactiveProperty v5.1.1 をリリースしました][]

- 機能説明

[ReactiveProperty][]や[ReactivePropertySlim][]を初期化するときに[ReactivePropertyMode][]を指定することで挙動を変更することができます。

[ReactivePropertyMode][]

| 要素 | 説明 |
|:-:|:-:|
| None | 指定なし |
| DistinctUntilChanged | この要素を追加すると、同じ値がきたら発火しない。どんな値でも漏らさず流したいなら外した方が良い |
| RaiseLatestValueOnSubscribe | Subscribeしたときの最初の一回を実行するか否かを指定できる。設定だけして今までのは流したくないなら外した方が良い |
| IgnoreInitialValidationError | SetValidateNotifyError等を設定しておいて最初の一回目のエラーは無視したい場合には追加した方が良い(例えば空の入力を許さないTextBoxだけど画面表示時はエラー表示を出したくないとか) |
| Default | DistinctUntilChanged と RaiseLatestValueOnSubscribe |


- 機能確認用

[ReactivePropertyMode](https://github.com/kwhrkzk/ReactivePropertySample/tree/master/ReactivePropertySample/ViewModule/ReactivePropertyMode)



[AsyncReactiveCommand]:https://github.com/runceel/ReactiveProperty/blob/master/Source/ReactiveProperty.NETStandard/AsyncReactiveCommand.cs
[ReactivePropertyMode]:https://github.com/runceel/ReactiveProperty/blob/master/Source/ReactiveProperty.NETStandard/ReactiveProperty.cs
[Pairwise]:https://github.com/runceel/ReactiveProperty/blob/master/Source/ReactiveProperty.NETStandard/Extensions/PairwiseObservableExtensions.cs
[BusyNotifier]:https://github.com/runceel/ReactiveProperty/blob/master/Source/ReactiveProperty.NETStandard/Notifiers/BusyNotifier.cs
[ReactivePropertySlim]:https://github.com/runceel/ReactiveProperty/blob/master/Source/ReactiveProperty.NETStandard/ReactivePropertySlim.cs
[ReactiveProperty]:https://github.com/runceel/ReactiveProperty/blob/master/Source/ReactiveProperty.NETStandard/ReactiveProperty.cs
[ReactivePropertySlim詳解]:http://neue.cc/2018/01/18_562.html
[ReactiveProperty : WPF/SL/WP7のためのRxとMVVMを繋ぐ拡張ライブラリ]:http://neue.cc/2011/10/07_346.html
[ReactivePropertyのNotifier系クラス]:https://code.msdn.microsoft.com/windowsdesktop/ReactivePropertyNotifier-c51f6e5a
[ReactiveProperty v2.9.0とv3.0.0-pre5をリリースしました。]:https://blog.okazuki.jp/entry/2016/07/20/182102
[ReactiveProperty ver 0.3.0.0 - MとVMのバインディングという捉え方]:http://neue.cc/2011/11/20_354.html
[MVVMをリアクティブプログラミングで快適にReactivePropertyオーバービュー]:https://blog.okazuki.jp/entry/2015/12/05/221154
[ReactiveProperty v5.1.1 をリリースしました]:https://blog.okazuki.jp/entry/2018/06/22/112213