我有一个包含以下标题的数据源:
IObservable<IObservable<object>> MagicSource(IObservable<string> strings)
我把字符串推到那里然后给我结果,但是考虑到我只需要最后一个字符串的答案,我使用Switch语句来取消之前的字符串:
MagicSource(StringsProvider).Switch().Subscribe(r => {/*...*/});
效果很好,但我还需要收到通知,目前正在处理的字符串已更改,以便准备我的结果视图。如何获得此类通知?
答案 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 => {/*...*/});