Closed kenichi-kobayashi closed 3 years ago
まだ深く追えてませんが、おそらく想定していない条件なのでバグだと思います。 確認してみます。
プロパティの Get アクセサーをリフレクションで取得してキャッシュしているのですが、型が途中で変わると Get アクセサーの呼び出しで型のミスマッチが起きてこけていました。
型が変わったタイミングで、Get アクセサーのキャッシュをクリアするようにして対応しました。
ありがとうございます。 相変わらずの爆速対応、感謝です。早速取り込んでみます。
NugetからV7.8.2を取得して、実験してみましたが、正しく動作しませんね。
上記プロジェクトで画面中央のボタンを押下すると、画面のテキストは「Grand2-Name3」になってほしいのですが、空になってしまいますね。
そちらは、また別の問題で ObserveProperty で監視しているプロパティ上の全ての型が INotifyPropertyChanged を実装していないために起きているのだと思います。
v7.8.3 で ObserveProperty で監視するプロパティの途中に INotifyPropertyChanged を実装していない型が来ているケースにも対応してみました。
整理すると以下の 2 つの問題がありました。
最初の v7.8.2 では 2 を解消して v7.8.3 では 1 を解消しました。 なので、v7.8.2 だと GrandBase に INotifyPropertyChanged を実装すると期待通りに動いて v7.8.3 だと修正しなくても期待通り動くと思います。
私も最初 1 のほうの動きを見落としていました。すいません。
かずきさん、修正を確認しました。無事に動きました。 本当に、ありがとうございました! 今回のネストしたプロパティの監視機能は、かなり強力で、すっきり記載ができるようになりました。 これ、かなり強力です。
そして、一つ質問させてください。
public ReactivePropertySlim
DisplayFullPath = SelectedNode.ObserveProperty(a => a.Value.DisplayFullPath).ToReadOnlyReactivePropertySlim().AddTo(disposables);
上記のようなコードを定義したとします。
SelectedNode.Value = null;
この状態で、上記のコードを書いた場合、ObserveProperty内の「a.Value.DisplayFullPath」で例外が発生するよな気がしていたのですが、特に例外にならなかったんですよね。
ネストしたプロパティでヌルポなりで、例外が発生した場合は、Defaultに戻すような仕様になっていますか? 動き的に、そのような動きに見えました。
ObserveProperty
の引数に渡している a.Value.DisplayFullPath
は式木なので、それを分析して監視対象のプロパティ名を取得するのに使っています。
途中の値が変わったときは、プロパティを 1 つずつ辿って行って途中で null があったら default
を返すような感じにしてます。
コード的にはわかりにくいかもしれませんが以下のフォルダーにある PropertyObservable.cs
や PropertyPathNode.cs
あたりが実際の ObserveProperty
でネストしたプロパティを渡したときの実態のコードです。
https://github.com/runceel/ReactiveProperty/tree/main/Source/ReactiveProperty.NETStandard/Internals
一旦 Issue 自体はクローズにします。
いつも、ReactivePropertの保守、開発ありがとうございます。 前回のIFilteredのReset対応の実験がまだ出来ていなくて連絡が遅くなってしまって、申し訳ないです。
そして、平行してV7.5.0で追加された「ネストしたプロパティのObserveProperty 」を使っています。 これを使うことで、劇的にスリム化されたコードがかける可能性があることを感じています。
そこで、一つ仕様を確認させてください。
ネスト対象のプロパティが、既定クラスが統一された別クラスが指定された場合、正しく動作しないのですが、これは、仕様でしょうか? 」 サンプルプログラムを作ってみました。 GrandBaseから派生したGrandAとGrandBを定義しています。
ReactivePropertyTest.zip
そして、上記のGrandBaseを格納できるRpを用意します。
public ReactivePropertySlim<GrandBase> GrandRp { get; set; } = new ReactivePropertySlim<GrandBase>();
このGrandRpからネスト関したしたRpを作ります。
var ChildName = GrandRp.ObserveProperty(a => a.Value.Parent.Child.Name).ToReadOnlyReactivePropertySlim().AddTo(disposables);
その場合に、ChildNameが空になって取得できませんでした。 これは、仕様でしょうか? これができると、使い方がかなり広がるので、非常にありがたいです。
ご検討のほど、よろしくお願いします。