在没有副作用的情况下,为Observable序列正确设置依赖谓词的函数方法是什么



我有三个可观察器oGotFocusOrDocumentSavedoGotFocusoLostFocus。我希望oGotFocusOrDocumentSaved仅在_active为真时才推送序列。我下面的实现可以根据需要工作,但它在_active上引入了一个副作用。有没有办法消除副作用,但仍然获得相同的功能?

class TestClass
{
  private bool _active = true;
  public TestClass(..)
  {
    ...
    var oLostFocus = Observable
      .FromEventPattern<EventArgs>(_view, "LostFocus")
      .Throttle(TimeSpan.FromMilliseconds(500));
    var oGotFocus = Observable
      .FromEventPattern<EventArgs>(_view, "GotFocus")
      .Throttle(TimeSpan.FromMilliseconds(500));
    var oGotFocusOrDocumentSaved = oDocumentSaved // some other observable
      .Merge<CustomEvtArgs>(oGotFocus)
      .Where(_ => _active)
      .Publish();
    var lostFocusDisposable = oLostFocus.Subscribe(_ => _active = false);
    var gotFocusDisposable  = oGotFocus.Subscribe(_ => _active = true);
    // use case
    oGotFocusOrDocumentSaved.Subscribe(x => DoSomethingWith(x));
    ...
  }
  ...
}

听起来你确实想要一个oDocumentSavedWhenHasFocus,而不是一个可观察的oGotFocusOrDocumentSaved

因此,尝试使用.Switch()运算符,如下所示:

var oDocumentSavedWhenHasFocus =
    oGotFocus
        .Select(x => oDocumentSaved.TakeUntil(oLostFocus))
        .Switch();

一旦您了解了.Switch()的工作原理,这一点就应该非常明显了。

SelectMany和TakeUntil的组合应该能让您到达需要的位置。

from g in oGotFocus
from d in oDocumentSaved
          .Merge<CustomEvtArgs>(oGotFocus)
          .TakeUntil(oLostFocus)

似乎希望在保存文档时收到通知,但前提是文档当前具有焦点。对的(您还希望在文档获得焦点时得到通知,但稍后可以很容易地将其合并。)

考虑窗口而不是事件;即通过巧合而加入。

您的需求可以表示为Join查询,从而将文档保存连接到焦点窗口,从而仅在两者重叠时产生通知;即当两者都处于"活动"状态时。

var oGotFocusOrDocumentSaved = 
  (from saved in oDocumentSaved
   join focused in oGotFocus
   on Observable.Empty<CustomEventArgs>()  // oDocumentSave has no duration
   equals oLostFocus // oGotFocus duration lasts until oLostFocus
   select saved)
   .Merge(oGotFocus);