我通过属性通过对象暴露了以下可观察对象。
IObservable<HumidityLevel> humidity;
但是直到调用该对象的方法之后才创建上述observable。但订阅者必须在构建暴露上述可观察对象的对象时进行订阅。
我能想到的一种方法是创建一个空的observable,以便订阅者可以订阅
IObservable<HumidityLevel> humidity = Observable.Empty<HumidityLevel>();
稍后在对象的生命周期中,当实际的observable准备就绪时,将其合并到上面的现有。
humidity = humidity.Concat(actualHumidityObservable)
现在上面的行显然修改了订阅者未订阅的湿度参考,因此他们永远不会听到此对象。
我如何实现我想要做的事情? Rx中是否有任何扩展可以合并到现有的observable中,以便保留订阅者?
答案 0 :(得分:3)
主体是关键,它们既是观察者又是观察者。除了通过它的On...
方法手动调用主题上的事件之外,您还可以直接将它们订阅到源可观察源 - 在主体自己的订阅者订阅之前或之后。
这是你可以这样做的一种方式:
public class HumidityLevel
{
public int Value;
}
public class Monitor
{
private Subject<HumidityLevel> _humidityLevel =
new Subject<HumidityLevel>();
public IObservable<HumidityLevel> HumidityLevel
{
get
{
return _humidityLevel.AsObservable();
}
}
public void StartMonitoring(IObservable<HumidityLevel> source)
{
source.Subscribe(_humidityLevel);
}
}
请注意在getter中使用AsObservable()
- 这是一种保护observable的原点作为基础Subject并因此被滥用的方法!
然后像这样使用它:
var monitor = new Monitor();
// a subscriber is free to subscribe at any time
var subscriber = monitor.HumidityLevel
.Subscribe(level => Console.WriteLine(level.Value));
// now create an example source
var source = Observable.Interval(TimeSpan.FromSeconds(1))
.Select(i => new HumidityLevel { Value = (int)i });
// and pass it to monitor and the subscriber will start getting events
monitor.StartMonitoring(source);
注意我在这里没有做任何清理,比如在你完成它之后取消订阅。您是否需要执行此操作以及如何执行此操作将取决于您的方案。这可能无关紧要,或者您可能希望跟踪订阅并在重新分配新源时将其释放。在这种情况下,您可能有兴趣将订阅存储在SerialDisposable
中。这里有很多选择。