Observable.FromEvent signature



Observable.FromEvent中拥有这样的签名的目的是什么?例如:

var appActivated = Observable.FromEvent(
h => Application.Current.Activated += h,
h => Application.Current.Activated -= h);

特别是,什么是h?为什么+=,然后-=?我们是从事件还是从事件处理程序进行Observable?如果来自事件,为什么不只有一个签名,例如:

var appActivated = Observable.FromEvent(Application.Current.Activated);
这是因为无法将

事件作为参数传递给方法。您可以作为委托人传入事件,但这并不能让您订阅/取消订阅事件。看看埃里克·利珀特的这个答案。

Observable.From基本上是说"好的,我会给你一个可观察量,它是事件的包装器,但你需要为我提供两个委托:1) 一个委托让我订阅我的处理程序到事件,2) 一个委托让我在需要时取消订阅我的处理程序"。

因此,在这种情况下h => Application.Current.Activated += h是一个编译为委托的 lambda 表达式。 h(处理程序)是输入参数,委托获取该输入参数并将其订阅到 Activated 事件。第二个委托是相同的,只是它取消订阅处理程序。

Eren 的回答是正确的;我想确保回答您的所有问题:

特别是,什么是h?

h 是添加和删除处理程序的委托的参数。调用时,h 将是对处理程序委托的引用。

为什么是+=,然后是-=?

可观察量需要能够订阅和取消订阅事件的处理程序。

我们是否从事件或事件处理程序中使可观察

从事件。

如果来自事件,为什么不只有一个签名,例如:var appActivated = Observable.FromEvent(Application.Current.Activated);

因为这将传递处理程序,而不是事件。"事件"是三件事:调用处理程序列表的能力、向列表中添加新处理程序的能力以及从列表中删除处理程序的能力。 可观察量需要最后两个;你的建议是通过第一个。 因此,可观察量需要执行最后两个操作的委托。

可观察量是 .NET 中的一类类型 - 这意味着您可以保留对它们的引用,并将它们作为参数传递给您喜欢的任何构造函数/方法。

事件不是第一类类型。它们只能在可以引用其包含对象的作用域中附加和分离。

所以这意味着我不能这样做:

    public void SomeMethod(EventHandler handler)
    {
        handler += (s, e) => { /* Handler Code */ };
    }
    public void SomeOtherMethod()
    {
        SomeMethod(Application.Current.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 中的一类类型传递。

相关内容

  • 没有找到相关文章

最新更新