我有一个类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));
}
}
}
到目前为止,我的尝试围绕着使用Publish
,RefCount
和Replay
。但是,如果我在触发事件后订阅了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做到这一点吗?
答案 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之后)。