为IObservable创建扩展方法

时间:2011-11-29 09:41:12

标签: c#-4.0 system.reactive

我需要将一些数据带入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(...)扩展方法?

2 个答案:

答案 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的任何正在运行的调用。您正在谈论的取消将需要由接口实现本身处理。