如何将回调转换为Rx.Observable?

时间:2017-01-15 21:45:44

标签: system.reactive

如果外部库仅提供注册回调而不是事件,那么从中创建Observable的最佳方法是什么?

如果它是我可以使用Observable.FromEventPattern的事件,但在这种情况下,我唯一的想法就是在每次回调时使用Subject并在其中排队事件。

有没有更好的方法呢?

3 个答案:

答案 0 :(得分:5)

使用Observable.Create.以下是一个例子:

void Main()
{
    var target = new SampleCallbacker();
    var actionB = new Action<int>(i => Console.WriteLine($"{i} * {i} = {i * i}."));
    target.Register(actionB);

    var observable = Observable.Create<int>(observer =>
    {
        var action = new Action<int>(i => observer.OnNext(i));
        target.Register(action);
        return () => target.Unregister(action);
    });

    var subscription = observable.Subscribe(i => Console.WriteLine($"From observable: {i} was fired."));

    target.Fire(1);
    target.Fire(2);
    target.Fire(3);
    Console.WriteLine("Unsusbscribing observable...");
    subscription.Dispose();
    target.Fire(4);
    target.Fire(5);
}

class SampleCallbacker
{
    private List<Action<int>> _actions = new List<System.Action<int>>();
    public void Register(Action<int> action)
    {
        _actions.Add(action);
    }

    public void Unregister(Action<int> action)
    {
        while (_actions.Remove(action))
        {} //loop remove
    }

    public void Fire(int i)
    {
        foreach (var action in _actions)
        {
            action(i);
        }
    }
}

答案 1 :(得分:0)

如果它是单个回调(例如,等待对查询的回复),那么您也可以使用StartAsync方法。大多数现代API都可能支持任务/承诺。

Observable.StartAsync<string>(cancellation =>
    {
        var source = new TaskCompletionSource<string>();
        yourlib.RegisterCallback(source.SetResult);
        cancellation.Register(() => yourlib.UnregisterCallback(source.SetResult));
        return source.Task;
    });

如果您想避免多次订阅,您可以随时使用.Publish().RefCount()共享一个订阅,当没有订阅者时,该订阅会被处理掉。

答案 2 :(得分:-1)

创建一个触发事件并将该方法作为回调传递的方法。