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

C# 如何切换()两个流,并在它们之间发出中间事件?,c#,system.reactive,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 用最后一个元素的单个串联突变简

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

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

用最后一个元素的单个串联突变简单地变换每个内部序列

IObservable<IObservable<T>> source = ...;
Func<T, T> mutation = ...;
IObservable<T> query = source
    .Select(innerSource => innerSource
        .Publish(o => o.Concat(o.LastAsync().Select(mutation))))
    .Concat();
IObservable源=。。。;
Func突变=。。。;
IObservable查询=源
.选择(innerSource=>innerSource
.Publish(o=>o.Concat(o.LastAsync().Select(mutation)))
.Concat();

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

只需使用最后一个元素的单个串联突变来转换每个内部序列

IObservable<IObservable<T>> source = ...;
Func<T, T> mutation = ...;
IObservable<T> query = source
    .Select(innerSource => innerSource
        .Publish(o => o.Concat(o.LastAsync().Select(mutation))))
    .Concat();
IObservable源=。。。;
Func突变=。。。;
IObservable查询=源
.选择(innerSource=>innerSource
.Publish(o=>o.Concat(o.LastAsync().Select(mutation)))
.Concat();

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

听起来您可能需要Concat而不是Switch。听起来好像一个流结束了,你得到了一个桥接值,然后你钩住了下一个流。这比开关更复杂

使用Switch,您可以获得:

  • A流开始
  • 从你的可观察到的流中流出的事件
  • 流B启动-您的可观察到的从A取消订阅并切换到B
  • 问题是,如果在旧流完成之前出现一个新流,那么旧流上的LastAsync将不会启动,也不会获得桥接事件

    如果您使用Concat,在流A完成之前,您的observable不会切换到流B,如果您使用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();
    
    IObservable源=。。。;
    Func突变=。。。;
    IObservable查询=源
    .选择(innerSource=>innerSource
    .Publish(o=>{
    //当源推送另一个值时结束此流
    var stream=o.TakeUntil(源);
    返回stream.Concat(stream.LastAsync().Select(mutation));
    })
    .Concat();
    

    可能有更好/更干净的方法来做到这一点。对于Rx,总是值得尝试一些看似复杂的方法,因为有时一种方法比其他方法简单得多。

    听起来你可能想要Concat而不是Switch。听起来好像一个流结束了,你得到了一个桥接值,然后你钩住了下一个流。这比开关更复杂

    使用Switch,您可以获得:

  • A流开始
  • 从你的可观察到的流中流出的事件
  • 流B启动-您的可观察到的从A取消订阅并切换到B
  • 问题是,如果在旧流完成之前出现一个新流,那么旧流上的LastAsync将不会启动,也不会获得桥接事件

    如果您使用Concat,在流A完成之前,您的observable不会切换到流B,如果您使用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();
    
    IObservable源=。。。;
    Func突变=。。。;
    IObservable查询=源
    .选择(innerSource=>innerSource
    .Publish(o=>{
    //当源推送另一个值时结束此流
    var stream=o.TakeUntil(源);
    返回stream.Concat(stream.LastAsync().Select(mutation));
    })
    .Concat();
    

    可能有更好/更干净的方法来做到这一点。对于Rx,总是值得尝试一些看似复杂的方法,因为有时一种方法比其他方法简单得多。

    反向流1事件3是什么意思?@Enigmativity我刚刚编辑以澄清。基本上,在构建桥接事件时,我需要访问第一个流中的最后一个事件“反向流1事件3”是什么意思?@Enigmativity我刚刚编辑以澄清。基本上,在构建桥接事件时,我需要访问第一个流中的最后一个事件