Observables 是 .NET 中的一等类型 - 这意味着您可以保留对它们的引用并将它们作为参数传递给您喜欢的任何构造函数/方法。
事件是不是一流的类型。它们只能在您可以引用它们的包含对象的范围内附加和分离。
所以这意味着我不能这样做:
public void SomeMethod(EventHandler handler)
{
handler += (s, e) => { /* Handler Code */ };
}
public void SomeOtherMethod()
{
SomeMethod(Application.Current.Activated);
}
如果我尝试得到错误:
事件 'Application.Activated' 只能出现在 += 或 -= 的左侧
这应该让你知道为什么你不能这样做var appActivated = Observable.FromEvent(Application.Current.Activated);。
那么,我该如何解决这个问题,以便在 SomeMethod 中附加事件?
方法如下:
public void SomeMethod(Action<EventHandler> addHandler)
{
addHandler((s, e) => { /* Handler Code */ });
}
public void SomeOtherMethod()
{
SomeMethod(h => Application.Current.Activated += h);
}
基本上,在SomeMethod方法中,参数不再是EventHandler,而是Action<EventHandler>。这意味着我不再试图传递事件本身 - 相反,我正在传递一种方法让被调用的代码将自身附加到我的事件。对SomeMethod 的调用中的h 是一个承诺,如果将来我有一个有效的处理程序,那么我可以通过调用Action<EventHandler> 来附加它。
假设我现在想编写一些知道如何附加和分离事件的代码。我现在需要这个代码:
public void SomeMethod(Action<EventHandler> addHandler, Action<EventHandler> removeHandler)
{
EventHandler handler = (s, e) => { /* Handler Code */ };
addHandler(handler);
/* Some Intervening Code */
removeHandler(handler);
}
public void SomeOtherMethod()
{
SomeMethod(h => Application.Current.Activated += h, h => Application.Current.Activated -= h);
}
在/* Some Intervening Code */ 代码中,处理程序被附加,在它被分离之后。
这将我们带到您问题中的代码:
var appActivated = Observable.FromEvent(
h => Application.Current.Activated += h,
h => Application.Current.Activated -= h);
这与上面的 SomeMethod 调用非常相似 - FromEvent 需要一种方法来附加和分离事件。 h 是一个承诺,上面写着“嘿,FromEvent,如果你能提供一个处理程序,当你将来需要它时,我保证这段代码会正确附加它。”或者,视情况而定。
现在,为了有点迂腐,您的代码实际上应该是:
IObservable<EventPattern<EventArgs>> appActivated =
Observable
.FromEventPattern<EventHandler, EventArgs>(
h => Application.Current.Activated += h,
h => Application.Current.Activated -= h);
现在我有一个IObservable<EventPattern<EventArgs>>,我可以重写SomeMethod,把它作为参数,这样写:
public IDisposable SomeMethod(IObservable<EventPattern<EventArgs>> appActivated)
{
return appActivated.Subscribe(ep => { /* Handler Code */ });
}
现在可以看到 Rx 的所有功能。 .Subscribe 方法不需要对原始事件的包含对象的任何引用,但它最终会在需要时调用h => Application.Current.Activated += h 进行附加和h => Application.Current.Activated -= h 分离。我现在可以有效地将事件作为 .NET 中的一等类型传递。