我需要将一些数据带入IObservable流。我想在IObservable上使用扩展方法来做到这一点,但我不知道该怎么做。
数据由具有此签名的简单类生成:
interface Process<TIn, TOut> {
void Do(TIn data);
event Action<TOut> Result;
}
即。要开始这个过程,我必须调用Do(...)
并将结果发送到事件Result(...)
。这不能改变!
我想将这些数据带入一个Rx进程,以这种方式处理用户输入:
subject.AsObservable<string> // this produces the observable of user inputs
.Throttle(TimeSpan.FromMilliseconds(typingDelay))
.DistinctUntilChanged()
.Process(myProcess) // this is what I need help for
.Switch()
.Subscribe(myConsumer)
这来自延迟用户输入的标准示例,该示例触发Hands-on Labs中的Web服务(或其他长期运行且必须是异步的)。
每当用户继续输入时,所有仍在“正在进行中”的可观察者都必须被取消(因此Switch()
)。因此,我的Process()
必须返回IObservable<IObservable<TOut>>
才能使交换机正常工作。
我真的被困在这里了。有没有人提示我如何编写这个Process(...)
扩展方法?
答案 0 :(得分:1)
我已经修改了你的Process
接口以正确使用泛型,并提供了一个虚拟的接口实现,如下所示:
interface IProcess<T, R>
{
void Do(T data);
event Action<IEnumerable<R>> Result;
}
public class ProcessImpl<T, R> : IProcess<T, R>
{
public void Do(T data) { }
public event Action<IEnumerable<R>> Result;
}
现在您可以像这样编写扩展方法:
public static IObservable<IObservable<R>> Process<T, R>(this T @this)
{
return Observable.Create<IObservable<R>>(o =>
{
var p = new ProcessImpl<T, R>();
var subscription =
Observable
.FromEvent<IEnumerable<R>>(
h => p.Result += h,
h => p.Result -= h)
.Take(1)
.Select(x => x.ToObservable())
.Subscribe(o);
p.Do(@this);
return subscription;
});
}
这对你有用吗?
答案 1 :(得分:1)
基本上,您的Process
扩展方法需要订阅源observable并输出另一个。类似的东西:
public static IObservable<TOut> Process<TIn, TOut>(this IObservable<TIn> source, IProcess<TIn, TOut> processor)
{
return Observable.Create((IObserver<TOut> obs) =>
{
var sourceSub = source.Subscribe(processor.Do);
var outSub = Observable.FromEvent<TOut>(h => processor.Result += h,
h => processor.Result -= h)
.Subscribe(obs);
return new System.Reactive.Disposables.CompositeDisposable(sourceSub, outSub);
});
}
我认为Switch不会做你希望的那样。当另一个可观察的可用时,所有Switch将做的是结束一个订阅。但是,结束订阅无法取消对接口方法Process.Do
的任何正在运行的调用。您正在谈论的取消将需要由接口实现本身处理。