使用Rx来限制来自非异步调用的回调

时间:2011-05-10 16:36:58

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

我的问题类似于this问题,但总是略有不同。

我目前正在使用一个简单模式的项目来异步接收基础数据更改的通知。

Class Foo负责订阅这些数据更改,并为类提供了一种方法,通过注册实现给定接口的类的实例来注册他们对这些更改的兴趣:

public Guid SubscribeToChanges(ISomeCallbackInterface callback)

Class Bar实现了这个回调并自行注册:

public class Bar : ISomeCallbackInterface
{
    ...
    //initialise instance of Foo class and subscribe to updates
    _foo.SubscribeToChanges(this);
    ...

    public void CallbackMethod(string id, IEnumerable<Tuple<string, int, object>> data)
    {
        ...
    }
}

理想情况下,我们希望限制这些回调,因为我们可以获得一个回调,将特定数据的值从x更改为y,然后在一秒的空间内返回x。查看Rx文档,使用DistinctUntilChanged运算符将是微不足道的。

然而,问题是如何创建一个IObservable集合,然后我可以将操作符应用于上面给出的回调实现。文档非常清楚如何从标准.Net事件或Begin ... / End ...方法对创建IObservable。

更新:正如Richard Szalay在评论中指出的那样,我需要与Throttle一起使用DistinctUntilChanged来实现我的需要。

再次感谢Richard,我也应该提到我需要能够取消订阅回调。在当前模型中,我只需在Foo实例上调用Unscubscribe(Guid subscriptionToken)。

1 个答案:

答案 0 :(得分:3)

我想到的唯一方法是使用ISomeCallbackInterfaceObservable.Create的自定义实现。尽管如此,这种解决方案仍然存在问题:

public static IObservable<Tuple<string,IEnumerable<Tuple<string, int, object>>> 
    FromCustomCallbackPattern(ISomeCallbackPublisher publisher)
{
    return Observable.CreateWithDisposable<T>(observer =>
    {
        var subject = new Subject<
            Tuple<string,IEnumerable<Tuple<string, int, object>>>();

        var callback = new ObservableSomeCallback(subject);

        Guid subscription = publisher.SubscribeToChanges(callback);

        return new CompositeDisposable(
            subject.Subscribe(observer),
            Disposable.Create(() => publisher.UnsubscribeFromChanges(subscription))
        );
    });
}

private class ObservableSomeCallback : ISomeCallbackInterface
{
    private IObserver<Tuple<string,IEnumerable<Tuple<string, int, object>>> observer;

    public ObservableSomeCallback(
        IObserver<Tuple<string,IEnumerable<Tuple<string, int, object>>> observer)
    {
        this.observer = observer;
    }

    public void CallbackMethod(string id, IEnumerable<Tuple<string, int, object>> data)
    {
        this.observer.OnNext(new Tuple<
            string,IEnumerable<Tuple<string, int, object>>(id, data));
    }
}
相关问题