从Action <t> </t> </t>获取IObservable <t>的最佳方法

时间:2014-05-06 00:08:19

标签: c# system.reactive

我有一个方法void OnAction(Action<Person> callback),我想使用反应式扩展(Rx)从中创建一个IObservable<T>

我找到了两种可以帮助我的方法:Observable.FromEvent()Observable.Start()

var observable = Observable.Start(() =>
                                              {
                                                  Person person = null;
                                                  _mngr.OnAction(p => person = p);
                                                  return person;
                                              });

  var observable = Observable.FromEvent<Person>(
                action => _mngr.OnAction(action), //Add Handler
                action => // Remove Handler
                {
                });

第一个有封闭,我必须评估if person != null

var foo= observable.Where(p =>
                          {
                if(p!=null) //...
                          });

第二个采用Action参数,将给定的事件处理程序与基础.NET事件分离......但OnAction方法不是.NET事件。

两种方式都很好,但(在我看来)闻起来......

那么,从OnAction方法创建IObservable的最佳方法是什么?

2 个答案:

答案 0 :(得分:2)

var personAsObservable
        = Observable.Create<Person>(observer => {
            _mngr.OnAction(person => {
                observer.OnNext(person);
                observer.OnCompleted();
            });
        });

如果您希望确保只调用此方法一次,则可以执行以下操作。

var publishedPerson = personaAsObservable.Replay(1);

publishedPerson.Connect();

publishedPerson.Subscribe(Console.WriteLine);
publishedPerson.Subscribe(Console.WriteLine);
publishedPerson.Subscribe(Console.WriteLine);
publishedPerson.Subscribe(Console.WriteLine);

答案 1 :(得分:2)

详细阐述克里斯的回答并提出你的意见。从这里开始:

var personAsObservable = Observable.Create<Person>(observer => {
    _mngr.OnAction(person => {
        observer.OnNext(person);
        observer.OnCompleted();
    });
    return Disposable.Empty;
});

就目前而言,这将导致为每个订阅者调用OnAction

避免这种情况的一般方法是发布 observable。发布流会导致订阅者共享事件。

Publish运算符返回可连接的observable 。这可以接受订阅者,但实际上不会订阅基础流,直到您调用Connect() - 一个返回IDisposable的方法,您可以使用该方法来控制与底层可观察对象的单一连接 - dispose它取消订阅。

有几个与发布相关的运算符可帮助您管理对基础流的订阅。

只要基础订阅正在运行,

RefCount就可以使用可连接的observable来管理连接并与订阅共享事件。完成后,后续订阅将重新启动。这可能足以满足您的需求。要使用它,请订阅以下内容(这是一种非常常见的Rx习语):

var personPub = personAsObservable.Publish().RefCount();

其他方法包括将Replay(n)附加到源可观察源,其中n个事件将被缓存并重放到在基础流完成后到达的子序列订阅者。因此,如果您只想获得一次结果,这将非常有用。请注意,您必须明确地在Connect上致电Replay。您也可以致电Publish并管理自己的连接。

请注意,附加这些运算符不会更改基础observable的行为 - 所有发布,缓存等都在附加的运算符上完成。因此,在上面的示例中,订阅者应该使用personPub

显式控制连接如下所示:

IConnectableObservable<Person> personPub = personAsObservable.Publish();
var subscriberOne = personPub.Subscribe(...); // personAsObservable not started
var connection = personPub.Connect(); // *now* personAsObservable is subscribed
var subscriberTwo = personPub.Subscribe(...); // shares underlying subscription
                                              // but could miss events
connection.Dispose(); // underlying connection terminated
                      // but may have already OnCompleted anyway
                      // in which case this is a no-op