【问题标题】:How do I get an IObservable to push the newest value upon subscription如何在订阅时获得 IObservable 以推送最新值
【发布时间】:2010-11-13 23:31:42
【问题描述】:

通常当您订阅一个值的更改时,您也有兴趣知道初始值。我希望我的 IObservable 缓存最新(或初始)值并将该值推送到订阅。

当使用普通事件时,我经常会得到看起来像这样的代码

x.SomeEvent += SomeEventHandler;
SomeEventHandler(x, EventArgs.Empty);

我希望使用 IObservable 来包装事件,以推动初始值。如果我有多个订阅者,他们应该在订阅时收到最新的值 如果我在创建 IObservable 后立即订阅,我有一些代码可以正常工作,但如果事件在订阅之前触发,则不会:

class Program
{
    static void Main()
    {
        var s = new Source { Value = 1 };
        var values = Observable.Return(s.Value).Concat(
            Observable.FromEvent(
                h => s.ValueChanged += h,
                h => s.ValueChanged -= h)
            .Select(_ => s.Value));
        using (values.Subscribe(Console.WriteLine))
        {
            s.Value = 2; // prints 1,2 as expected
        }
        using (values.Subscribe(Console.WriteLine))
        {
            s.Value = 3; // prints 1,3 - expected 2,3
        }
    }
}

class Source
{
    private int _value;
    public int Value
    {
        get { return _value; }
        set
        {
            if (_value == value)
                return;
            _value = value;
            if (ValueChanged != null)
                ValueChanged(this, EventArgs.Empty);
        }
    }

    public event EventHandler ValueChanged;
}

如何创建按预期工作的 IObservable?

【问题讨论】:

  • .Select(_ => s.Value) - 这很奇怪,可能会破坏。您不能更改ValueChanged 事件以使事件参数包含新值吗?
  • 我正在听的代码不是我写的。如果我是,我只会公开一个 IObservable :)

标签: c# system.reactive


【解决方案1】:

解决方案是将BehaviorSubject 订阅到可观察对象,并将所有观察者订阅到BehaviorSubjectBehaviorSubject 会记住最后的通知,并在订阅时通知新的观察者。

查看具有initialValue 参数的Observable.Publish 扩展方法。这将创建一个内部使用 BehaviorSubjectIConnectableObservable

var s = new Source { Value = 1 };

var values = Observable.FromEvent(h => s.ValueChanged += h,
                                  h => s.ValueChanged -= h)
                       .Select(e => e.NewValue)
                       .Publish(s.Value);

using (values.Connect())                         // subscribes subject to event
{
    using (values.Subscribe(Console.WriteLine))  // subscribes to subject
    {
        s.Value = 2;
    }                                            // unsubscribes from subject

    using (values.Subscribe(Console.WriteLine))  // subscribes to subject
    {
        s.Value = 3;
    }                                            // unsubscribes from subject

}                                            // unsubscribes subject from event

(未经测试)

【讨论】:

    猜你喜欢
    • 2023-04-02
    • 2015-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多