发布新订阅者的最后一个事件值

时间:2015-08-17 13:00:36

标签: c# system.reactive

我有一个类Foo,其中包含一个发布FooState枚举的事件。我想把这个事件变成一个可以重放新订阅者的最后一个值的observable。

即使没有订阅者,任何新订阅者都应该获得最后一个值。

public enum FooState
{
    Stopped = 0,
    Starting = 1,
    Running = 2,        
}

public delegate void FooEventHandler(object sender, FooEventArgs e);

public class FooEventArgs : EventArgs
{
    public FooEventArgs(FooState fooState)
    {
        this.State = fooState;
    }

    public FooState State {get; private set;}
}

public class Foo
{
    public event FooEventHandler FooEvent;

    public void OnFooEvent(FooState state)
    {
        var fooEvent = FooEvent;

        if(fooEvent != null)
        {
            fooEvent(this, new FooEventArgs(state));
        }
    }
}

到目前为止,我的尝试围绕着使用PublishRefCountReplay。但是,如果我在触发事件后订阅了observable,那么我试过的组合都没有。

Replay(1).RefCount()只要已经有至少一个订阅,但我也需要为第一个延迟订阅工作。

var foo = new Foo();

   var obs =  Observable.FromEventPattern<FooEventHandler, FooEventArgs>(
                                        h => foo.FooEvent += h,
                                        h => foo.FooEvent -= h)
                                    .DistinctUntilChanged()
                                    .Replay(1)
                                    .RefCount();

    // Works if this line is uncomented.
    //obs.Subscribe(x => Console.WriteLine("Early Subscriber = " + x.EventArgs.State));

    foo.OnFooEvent(FooState.Running);

    obs.Subscribe(x => Console.WriteLine("Late Subscriber = " + x.EventArgs.State));

有人知道如何使用Rx做到这一点吗?

2 个答案:

答案 0 :(得分:3)

RefCount仅在第一次订阅后才会连接。如果您希望对连接何时进行细粒度控制,则应使用Replay + Connect

所以改为:

var publishedSource = eventSource.DistinctUntilChanged().Replay(1);

var connection = publishedSource.Connect();

//Subscribe to publishedSource to receive events and dispose of 
connection when you are done.

从我的手机发布,所以提前为任何语法错误道歉。

答案 1 :(得分:1)

Rx正在做正确的事情,将您的事件通知转换为您的流并重播它们,但您要问的是: &#34;为什么当我订阅活动时,我没有得到初始状态&#34;。

事件并非如此。如果我在foo.FooEvent上做+ =,我不会立即获得当前值的触发器。我只会在变化时收到通知。 正如您所注意到的那样,重播&#39;将重播后续事件,但不会在订阅时提供状态。

要解决您的问题,您需要确保在连接流以进行更改通知之前将当前值放入流中。 查看Observable.StartWith()。

即。做&#34; .StartWith(foo.State)&#34;在.DistinctUntilChanged()调用之前(紧跟在.FromEventPattern之后)。