如何确定Switch改变了输出?

时间:2013-08-16 14:27:47

标签: c# system.reactive

我有一个包含以下标题的数据源:

IObservable<IObservable<object>> MagicSource(IObservable<string> strings)

我把字符串推到那里然后给我结果,但是考虑到我只需要最后一个字符串的答案,我使用Switch语句来取消之前的字符串:

MagicSource(StringsProvider).Switch().Subscribe(r => {/*...*/});

效果很好,但我还需要收到通知,目前正在处理的字符串已更改,以便准备我的结果视图。如何获得此类通知?

4 个答案:

答案 0 :(得分:1)

最简单的方法是使用Do语句:

以下是一些品种。

如果您对MagicSource的工作原理一无所知,并且无法将新传入的字符串与新的内部流完全相关:

Action NewStreamProduced = ...;
MagicSource(StringsProvider).Do(_ => NewStreamProduced).Switch()....

如果您确实知道每次新字符串到达​​时MagicSource将同步生成新的内部流,那么您可以在调用Do之前放置MagicSource

Action<string> NewStringArrivedWhichMeansWeAreSwitching = ...;
MagicSource(StringsProvider.Do(NewStringArrivedWhichMeansWeAreSwitching)).Switch()...

答案 1 :(得分:1)

您应该为每个元素添加一个索引,指示它来自哪个子源。很简单。

IObservable<Tuple<string, int>> results =
 MagicSource(StringsProvider)
 .Select((v,i)=>v.Select(y=>Tuple.Create(y,i))
 .Switch()

答案 2 :(得分:1)

实际上最好的方法如下。您需要使用多播。

// Ensure that you are using multicast
var source = MagicSource(strings).Publish().RefCount();

// Subscribe to this for notification and count
var notifications = source.Select((v,i)=>i);

// Subscribe to this to get flattened data
var flattened = source.Switch()

执行Publish().RefCount()会创建一个组播源,在第一次订阅时订阅一次,然后在删除最后一个订阅时取消订阅。需要记住的重要一点是,只有一次订阅源可能会或可能不重要。

答案 3 :(得分:1)

我个人会避免使用Do语句。

您可以创建投影。

在这个投影中,我假设您想要处理当前内部序列(可能从表中清除当前记录?)

MagicSource(StringsProvider)
    .Select(inner=>inner.Finally(CleanUp))
    .Switch()
    .Subscribe(r => {/*...*/});

如果你想做同样的事情,但是目标是内部序列的订阅(而不是处置),那么你还有一些工作要做。我会创建最终的对称运算符Initially(Action)

public static class ObservableEx
{
    public static IObservable<T> Initially<T>(this IObservable<T> source, Action onSubscribe)
    {
        return Observable.Create<T>(o=>{
            try
            {           
                onSubscribe();
                return source.Subscribe(o);
            }
            catch (Exception ex)
            {
                o.OnError(ex);
                return Disposable.Empty;
            }
        });
    }
}

然后你可以像这样使用它

MagicSource(StringsProvider)
    .Select(inner=>inner.Initially(Prepare))
    .Switch()
    .Subscribe(r => {/*...*/});