C# 可观察。其中使用异步谓词
有没有一种方便的方法可以使用异步函数作为可观察对象上Where运算符的谓词 例如,如果我有一个整洁但可能长期运行的函数,定义如下:C# 可观察。其中使用异步谓词,c#,async-await,system.reactive,C#,Async Await,System.reactive,有没有一种方便的方法可以使用异步函数作为可观察对象上Where运算符的谓词 例如,如果我有一个整洁但可能长期运行的函数,定义如下: Task<int> Rank(object item); public static IObservable<T> Where<T>( this IObservable<T> source, Func<T, Task<bool>> predicate) { return sou
Task<int> Rank(object item);
public static IObservable<T> Where<T>(
this IObservable<T> source, Func<T, Task<bool>> predicate)
{
return source.SelectMany(item =>
predicate(item).ToObservable()
.Select(include => include ? Observable.Return(item) : Observable.Empty<T>())
);
}
在过去,当我需要这样做时,我会使用SelectMany并将这些结果与原始值一起投影到一个新类型中,然后在此基础上进行过滤
myObservable.SelectMany(async item => new
{
ShouldInclude = (await Rank(item)) > 5,
Item = item
})
.Where(o => o.ShouldInclude)
.Select(o => o.Item);
我觉得这太难理解了,我觉得一定有更干净的方法
我觉得那太难读了
是的,但是您可以通过将其封装到helper方法中来解决这个问题。如果将其命名为Where,您将获得所需的语法:
public static IObservable<T> Where<T>(
this IObservable<T> source, Func<T, Task<bool>> predicate)
{
return source.SelectMany(async item => new
{
ShouldInclude = await predicate(item),
Item = item
})
.Where(x => x.ShouldInclude)
.Select(x => x.Item);
}
或者,您可以使用以下内容:
Task<int> Rank(object item);
public static IObservable<T> Where<T>(
this IObservable<T> source, Func<T, Task<bool>> predicate)
{
return source.SelectMany(item =>
predicate(item).ToObservable()
.Select(include => include ? Observable.Return(item) : Observable.Empty<T>())
);
}
事实上,@svick的答案有更少的闭包 您希望项目在排名完成时进入结果流,还是它们会保持其原始顺序?我对两者都感兴趣,但假设在这种情况下,顺序不受关注。+1。这可能是最简单的解决方案,实际上很好。我真不敢相信我以前从未想到过。为什么要用Map来代替更常见的名称,至少在C选择中是这样?Map是标准的函数编程术语。Select是原始LINQ到SQL实现遗留下来的术语。据我所知,Map不存在于Rx的.NET版本中,但存在于RxJS中。基本上,我只是习惯于编写映射而不是选择。实际上,在System.Reactive.Observable.Alias命名空间中。啊,在这种情况下,我可能会在.NET中开始使用它,以与世界其他地方保持一致