是否存在懒惰可观察的东西?

时间:2014-07-05 15:41:09

标签: system.reactive reactive-programming observable

我通过属性通过对象暴露了以下可观察对象。

IObservable<HumidityLevel> humidity;

但是直到调用该对象的方法之后才创建上述observable。但订阅者必须在构建暴露上述可观察对象的对象时进行订阅。

我能想到的一种方法是创建一个空的observable,以便订阅者可以订阅

 IObservable<HumidityLevel> humidity = Observable.Empty<HumidityLevel>();

稍后在对象的生命周期中,当实际的observable准备就绪时,将其合并到上面的现有。

 humidity = humidity.Concat(actualHumidityObservable)

现在上面的行显然修改了订阅者未订阅的湿度参考,因此他们永远不会听到此对象。

我如何实现我想要做的事情? Rx中是否有任何扩展可以合并到现有的observable中,以便保留订阅者?

1 个答案:

答案 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中。这里有很多选择。