【问题标题】:How to unwrap nested IObservable aka IObservable<IObservable<T>>如何解开嵌套的 IObservable 又名 IObservable<IObservable<T>>
【发布时间】:2020-05-22 18:21:47
【问题描述】:

我正在尝试从以下代码创建一个IObservable&lt;string&gt;,但我似乎无法找到正确解开事件处理程序值的方法。

发生的情况是 PasswordBox 可能会更改,因此无论何时我都想观察它,并在引发密码更改事件时提供字符串资源。如果我对普通事件执行此操作,它工作正常,但我很好奇使用 System.Reactive 将如何工作。

        var passwordChanged = WhenPropertyChanged
            .Where(name => nameof(PasswordBox) == name)
            .Select(d => PasswordBox)
            .Where(d => d != null)
            .Select(box =>
            {
                return Observable.FromEvent<RoutedEventHandler, RoutedEventArgs>(
                    handler => box.PasswordChanged += handler,
                    handler => box.PasswordChanged -= handler);
            }).Select(d => nameof(Password));

对我来说,在 Select(box => ... 部分中似乎必须有某种方式可以返回不同的对象(IObservable&lt;IObservable&lt;RoutedEventArgs&gt;&gt; 除外),该对象可用于正确订阅。

像下面这样工作。但我认为如果你端到端使用响应式,它可以更好地避免事件处理程序内存泄漏。

        var passwordHasChanged = new Subject<string>();
        // listen for changes of the password
        WhenPropertyChanged
            .Where(name => nameof(PasswordBox) == name)
            .Select(d => PasswordBox)
            .Where(d => d != null)
            .Subscribe(box =>
            {
                box.PasswordChanged += (sender, args) => passwordHasChanged.OnNext(nameof(Password));
            });

        passwordHasChanged.Subscribe(d => Log.Debug("Password changed"));

【问题讨论】:

    标签: c# system.reactive


    【解决方案1】:

    尽可能避免使用主题。主题就像 Rx 的可变变量,它们不是命令式的而不是声明式的。

    如果您只需要最后一次密码输入的事件,请使用Switch

    SwitchIObservable&lt;IObservable&lt;T&gt;&gt; 上工作,并在获得更新的 observable 时取消订阅之前的 observable。

       var passwordChanged = WhenPropertyChanged
                .Where(name => nameof(PasswordBox) == name)
                .Select(d => PasswordBox)
                .Where(d => d != null)
                .Select(box =>                
                    Observable.FromEvent<RoutedEventHandler, RoutedEventArgs>(
                        handler => box.PasswordChanged += handler,
                        handler => box.PasswordChanged -= handler);
                )
                .Switch()
                .Select(d => nameof(Password));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多