c# Observable Subject 冷热

c# Observable subject hot and cold

我经常遇到这样的情况,我想要一个 UI 元素到 "watch" 一个基础值 - 假设我正在显示一个 int - 我想要一个我可以订阅的 IObservable。

我下面一直用的是Subject,直接设置就可以了。这真的很好用……除了第一次。如果我设置主题 - 然后稍后通过打开一个新的 UI 元素来订阅它 - 它不会触发 onnext 直到下一次更改。

我基本上想要像主题一样工作的东西 - 但总是立即对任何新订阅者执行最新值的 onNext。

我知道我可以自己编写这样的结构 - 但它似乎是一个常见的用例 - 我是否缺少一些标准?

您想要 BehaviorSubject<T>ReplaySubject<T>

BehaviorSubject<T> 重播最近的单个值,并要求您在构造函数中提供初始值。

你这样使用它:

var bs = new BehaviorSubject<int>(0);
bs.Subscribe(x => Console.WriteLine(x));
bs.OnNext(42);
bs.Subscribe(x => Console.WriteLine(x));

这将输出 0,然后 42,然后 42 到控制台。

ReplaySubject<T> 比较笼统。它允许您指定要重播的值的数量,但不强制您提供初始值。

var rs = new ReplaySubject<int>(1);
rs.Subscribe(x => Console.WriteLine(x));
rs.OnNext(42);
rs.Subscribe(x => Console.WriteLine(x));

这会生成 42,然后 42 到控制台。

将此与标准 Subject<T> 进行比较。

var s = new Subject<int>();
s.Subscribe(x => Console.WriteLine(x));
s.OnNext(42);
s.Subscribe(x => Console.WriteLine(x));

那只会产生 42.

如果你在 UI 中使用 Rx,你应该看看 ReactiveUI

它有方便的扩展 .ToProperty 和更多:

_isValid = this.WhenAnyValue(x => x.Username, x => x.Password, (user, password) => !string.IsNullOrEmpty(user) && !string.IsNullOrEmpty(password)).ToProperty(this, x => x.IsValid);

public bool IsValid => _isValid.Value;

这基本上就是您正在做的事情:

  • this.WhenAnyValue(x => x.Property) => 属性 可观察
  • obs.ToProperty() => 可观察到 属性,您可以绑定到 UI

都适用于 INotifyPropertyChanged