如何打开嵌套的 IObservable aka IObservable<IObservable<T>>
How to unwrap nested IObservable aka IObservable<IObservable<T>>
我正在尝试从以下代码创建一个 IObservable<string>
,但我似乎无法找到一种方法来正确解包事件处理程序的值。
发生的事情是 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 => ... 部分我可以 return 一个不同的对象(除了 IObservable<IObservable<RoutedEventArgs>>
), 可用于正确订阅
像下面的作品那样做。但我认为如果端到端使用反应式,它可以更好地避免事件处理程序内存泄漏。
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"));
尽可能避免使用主题。 Subjects 就像 Rx 的可变变量,它们不是命令式的而不是声明式的组合和阅读。
如果您只需要最后一次输入密码的事件,请使用 Switch
。
Switch
在 IObservable<IObservable<T>>
上工作,并在获得更新的可观察对象时取消订阅先前的可观察对象。
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));
我正在尝试从以下代码创建一个 IObservable<string>
,但我似乎无法找到一种方法来正确解包事件处理程序的值。
发生的事情是 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 => ... 部分我可以 return 一个不同的对象(除了 IObservable<IObservable<RoutedEventArgs>>
), 可用于正确订阅
像下面的作品那样做。但我认为如果端到端使用反应式,它可以更好地避免事件处理程序内存泄漏。
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"));
尽可能避免使用主题。 Subjects 就像 Rx 的可变变量,它们不是命令式的而不是声明式的组合和阅读。
如果您只需要最后一次输入密码的事件,请使用 Switch
。
Switch
在 IObservable<IObservable<T>>
上工作,并在获得更新的可观察对象时取消订阅先前的可观察对象。
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));