如何Switch()两个流,并在它们之间发出中间事件?

时间:2015-08-21 09:23:16

标签: c# system.reactive

我有一条流媒体。当一个流结束,然后下一个流开始时,我需要发出一个桥接它们的中间事件。这需要在上一个流的最后一个事件之后发生,并且需要改变最后一个事件的状态。基本上,输出流需要如下所示:

Stream 1 - event 1
Stream 1 - event 2
Stream 1 - event 3  (Stream 1 completes)
* My bridging event (Mutation of event 3)
Stream 2 - event 1 etc

2 个答案:

答案 0 :(得分:3)

使用最后一个元素的单个连锁变异简单地转换每个内部序列。

IObservable<IObservable<T>> source = ...;
Func<T, T> mutation = ...;
IObservable<T> query = source
    .Select(innerSource => innerSource
        .Publish(o => o.Concat(o.LastAsync().Select(mutation))))
    .Concat();

请注意,这假设每个内部流始终至少有一个项目。

答案 1 :(得分:2)

听起来你可能想要Concat而不是Switch。听起来像一个流结束,你得到一个桥接值,然后你挂钩到下一个流。这是Concat而不是Switch。

使用Switch,您可能会得到:

  1. 流A开始
  2. 来自A stream的事件通过您的observable
  3. 流B开始 - 您的可观察取消订阅A并切换到B
  4. 问题是,如果在旧流完成之前出现新流,则旧流上的LastAsync将不会触发,您将无法获得桥接事件。

    如果你使用的是Concat,你的observable将不会切换到流B,直到流A完成,如果你使用Timothy Shields的方法,你将在A结束时得到你的最后一个变异值。

    但是,如果您遇到的情况是您希望在新流到达时立即切换,但是您希望在那时进行桥接事件,那么它会更棘手。它可能必须是Timothy Shields答案的改编版本,如:

    IObservable<IObservable<T>> source = ...;
    Func<T, T> mutation = ...;
    IObservable<T> query = source
        .Select(innerSource => innerSource
            .Publish(o => {
                   // end this stream when source pushes another value
                   var stream = o.TakeUntil(source);
                   return stream.Concat(stream.LastAsync().Select(mutation)));
                   })
            .Concat();
    

    可能有更好/更清洁的方法。使用Rx,总是值得尝试一些看起来很复杂的东西,因为有时候一种方式比其他方式简单得多。