いつもどこかでデスマーチ♪

不定期に、私の日常を書き込みしていきます。

C# クラス内の全ReactivePropertyのSubscribeに同じメソッドを登録する

2021年07月09日 11時56分32秒 | .NET系
やり方を拝借したのはここ:
https://tamafuyou.hatenablog.com/entry/2016/10/29/020651

感謝感激です!ココが無ければ諦めてた…ってわけで、詳しくは上記ブログを見てね!(投げやり)

ただ、自分のやりたい事をやろうとしたとき、「どうにかならんかなぁー」って感じ

現状:
1.DataクラスにReactiveProperty を沢山保持(DBやらCSVなどのデータをまとめたいから)
2.DataクラスのReactiveProperty を画面に直接参照させてる。(ViewMode内のプロパティがたくさんできるのが嫌)
3.データを1つのダイアログ内で全部表示・編集させてる

やりたい事:
・ユーザが変更した時は「保存ボタン」を押せなくするが、「別名保存ボタン」は押せるようにしたい。
ってなるので、Dataクラス内の全ReactivePropertyに同じSubscribeを登録したかった。
エラーの有無は「ObserveHasErrors」と「CombineLatest」を全部チェックさせるしかないけど、
Subscribeを全部登録するのは面倒すぎたので探してた。

で、こうなった

/// <summary>
/// 画面データクラスの元
/// </summary>
[DataContract]
public abstract class AbstractBase
{
    /// <summary>
    /// 全てのReactiveProperty に Subscribeを追加します
    /// </summary>
    /// <param name="action">値変更時に呼び出されるメソッド<名称, 値></param>
    public void SubscribeAllReactiveProperty(Action<object, string, object> action)
    {
        var disposes = this.GetType()
                           .GetProperties()
                           .Where(x =>
                                  x.PropertyType.Name.StartsWith(nameof(ReactiveProperty)) ||
                                  x.PropertyType.Name.StartsWith(nameof(ReadOnlyReactiveProperty)))
                           .Select(x =>
                                   System.Linq.Expressions.Expression.Lambda(System.Linq.Expressions.Expression.Call(this.GetType(),
                                                                                                                     nameof(RelaySubscribe),
                                                                                                                     new[] { x.PropertyType.GetGenericArguments().First() },
                                                                                                                     System.Linq.Expressions.Expression.Constant(x.GetValue(this)),
                                                                                                                     System.Linq.Expressions.Expression.Constant(x.Name),
                                                                                                                     System.Linq.Expressions.Expression.Constant(action)))
                                                                     .Compile().DynamicInvoke() as IDisposable)
                            .ToList();
    }
    /// <summary>
    /// 全てのReactiveProperty に subscribe を登録します
    /// </summary>
    /// <typeparam name="TT">ReactivePropertyの型</typeparam>
    /// <param name="source">ReactiveProperty</param>
    /// <param name="name">プロパティ名称</param>
    /// <param name="action">呼び出すアクション</param>
    /// <returns></returns>
    public static IDisposable RelaySubscribe(IObservable source, string name, Action<object, string, object> action)
    {
        return source.Subscribe(x =>
        {
            action(source, name, x);
        });
    }
    /// <summary>
    /// Subscribeの登録を破棄します
    /// </summary>
    public void DisposeSubscribeAllReactiveProperty()
    {
        if (SubscribePropertys != null)
        {
            foreach (var tmp in SubscribePropertys)
            {
                tmp.Dispose();
            }
        }
    }
}



使い方はこんな感じ:
public ReactiveProperty<SettingData> SettingData { get; set; }

public コンストラクタ(SettingService settingService){
    SettingData = settingService.SettingData;
    SettingData.Value.SubscribeAllReactiveProperty(Sample);
}

private void Sample(object sender, string name, object value)
{
    // いずれかのプロパティで変更があった時の処理
}



これで、全てのReactivePropertyの変更通知をSampleメソッドで一括処理できるようになりました。
データの差分が無いかを確認し、ReactiveProperty<bool> に値を保持すれば、ボタン制御に使える!
しかし、PropertyInfo から ReactiveProperty にキャスト(isやas)出来ないっぽいので、大変ですな…
まぁ、画面と1対1のデータのはずだからこんなことする方が少ないんだろうけどね。

後、ダイアログで使ってるから、ダイアログ破棄時に「DisposeSubscribeAllReactiveProperty」メソッドの呼び忘れをしなければ良いかなと…
メモリリークしてないよな…多分…自己責任で!

検索用:C# WPF ReactiveProperty Subscribe 全部 全て 同じメソッド 登録 追加 設定 一括 変更通知
コメント    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« OMV5 は raspberry pi zero ... | トップ | Appleは嫌い »

コメントを投稿

ブログ作成者から承認されるまでコメントは反映されません。

.NET系」カテゴリの最新記事