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
我经常遇到这样的情况,我想要一个 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