IObservable的Where()扩展方法是如何实现的?

时间:2012-04-03 13:31:34

标签: c#-4.0 functional-programming system.reactive

我一直在努力通过跟随Bart De Smetts MinLinq和Jon Skeets' Reimplementing'更加深入地了解Rx。我已经建立了一个很好的理解但是......

以下面的代码为例

var onePerSecond = Observable.Interval(TimeSpan.FromSeconds(1));
var evenNums = onePerSecond.Where(x => x % 2 == 0);
evenNums.Subscribe(Console.WriteLine);

从equivelant IEnumerable 的角度来看,我理解MoveNext / Current的数据流,以及来自Skeets先生的数据流。博客如何使用foreach而不是IEnumerable来实现Where方法'这个'扩展方法的参数。

但是对于IObservable的Where方法,它是否包含实现IObserver接口(或lambda equivelant)的代码,因此有效地观察来自onePerSecond对象的所有通知,然后返回一个IObservable只包含谓词发现为真的值?

非常欢迎任何帮助和想法,非常感谢

詹姆斯

2 个答案:

答案 0 :(得分:3)

通过查看ILSpy的源代码,很容易看出究竟是如何实现的。它返回一个新的observable,它根据你传递的谓词过滤项目:

public static IObservable<TSource> Where<TSource>(this IObservable<TSource> source, Func<TSource, bool> predicate)
{
    if (source == null)
    {
        throw new ArgumentNullException("source");
    }
    if (predicate == null)
    {
        throw new ArgumentNullException("predicate");
    }
    return new AnonymousObservable<TSource>((IObserver<TSource> observer) => source.Subscribe(delegate(TSource x)
    {
        bool flag;
        try
        {
            flag = predicate(x);
        }
        catch (Exception error)
        {
            observer.OnError(error);
            return;
        }
        if (flag)
        {
            observer.OnNext(x);
        }
    }
    , new Action<Exception>(observer.OnError), new Action(observer.OnCompleted)));
}

答案 1 :(得分:1)

以下是一些玩具示例,以了解它的工作原理:

https://github.com/ScottWeinstein/Rx-Demo/tree/master/ImplementWhereDemo

public class WhereObservableLessPedantic<T> : IObservable<T>
{
    private Func<T, bool> _pred;
    private IObservable<T> _stream;

    public WhereObservableLessPedantic(IObservable<T> stream, Func<T, bool> pred)
    {
        _pred = pred;
        _stream = stream;
    }

    public IDisposable Subscribe(IObserver<T> downStreamObserver)
    {
        Action<T> onNext = nextVal =>
        {
            if (_pred(nextVal))
                downStreamObserver.OnNext(nextVal);
        };
        return _stream.Subscribe(onNext);
    }
}


public class WhereObserverPedantic<T> : IObserver<T>
{
    private IObserver<T> _downStreamObserver;
    private Func<T, bool> _pred;

    public WhereObserverPedantic(IObserver<T> downStreamObserver, Func<T, bool> pred)
    {
        _pred = pred;
        _downStreamObserver = downStreamObserver;
    }

    public void OnNext(T value)
    {
        if (_pred(value))
        {
            _downStreamObserver.OnNext(value);
        }
    }

    public void OnCompleted() { }
    public void OnError(Exception error) { }
}