将事件作为参数传递到方法中

4

我想将一个事件传递到一个方法中。我已经写好了下面的代码,但是我应该在类型 "XXX" 中填写什么?

internal class Retriever<TEventArgs> where TEventArgs : EventArgs
{
    public Retriever( XXX event, EventHandler<TEventArgs> handler )
    {
        _event = event;
        _handler = handler;

        _event += handler;
    }

    XXX _event;
    EventHandler<TEventArgs> _handler;
}

编辑: 问题的详细说明。我正在尝试编写一个通用的事件守卫,其中事件在事件发生之前进行订阅,并在事件发生后取消订阅。该类应如下所示:

internal class EventGuard<TEventArgs> : IDisposable where TEventArgs : EventArgs 
{
    public Retriever( XXX event, EventHandler<TEventArgs> handler )
    {
        _event = event;
        _handler = handler;

        _event += handler;
    }

    XXX _event;
    EventHandler<TEventArgs> _handler;

    public void Dispose()
    {
        _event -= _handler;
    }
}

我会以下面的方式使用它。 Proxy.RetrieveAsync 是一个Web方法,完成后会触发Proxy.RetrieveCompleted事件。 完成处理程序HandleRetrieveCompleted的主体(未显示)将在手动重置事件上调用Set(传递为UserState对象)。

using ( new EventGuard<EventArgs>( Proxy.RetrieveCompleted, new  EventHandler<EventArgs>( HandleRetrieveCompleted) ) )
{
    ManualResetEvent resetEvent = new ManualResetEvent();
    Proxy.RetrieveAsync(resetEvent);
    resetEvent.WaitOne();

}
1个回答

6

您不需要 - 事件就像属性一样,它只是一对方法的语法糖(使用 add/remove 而不是属性的 get/set)。F# 实际上将事件公开为一级公民,但 C# 不支持 :(

不过,有几个选项:

  • Pass in an "event subscriber" delegate that you call with the new handler you want to add (and potentially an event unsubscriber delegate too). Something like this:

    new Receiver(handler => button.Click += handler, ...)
    
  • Pass in an EventInfo and subscribe with reflection (urgh)

  • Look into the Reactive Extensions framework, which has various ways of working with events (using reflection, but it means Microsoft does the reflection work rather than you :)
我们如果了解更大的背景,就可以给出更好的建议 - 您能否告诉我们更多信息?
编辑:好的,在这种情况下,您需要传递订阅和取消订阅代码。
using (new EventGuard<EventArgs>(h => Proxy.RetrieveCompleted += h, 
          h => Proxy.RetrieveCompleted -= h,
          HandleRetrieveCompleted))
{
    ...
}

诚然,这相当糟糕。你可能会发现在响应式扩展中有更好的方案,但至少这个能够工作...


我已经编辑了问题,以便更清楚地说明我想要实现的目标。 - Phillip Ngan
哎呀,这个问题加上多个类不能发布相同的事件,再加上使用强引用的事件(这是C#程序中内存泄漏的主要原因之一),再加上他们使用非常冗长的语法(每次调用都必须手动检查空值?真的吗!)……我认为在C# 5.0中需要对事件进行完全重构。 - BlueRaja - Danny Pflughoeft
@BlueRaja-DannyPflughoeft 我认为代码冗长的问题也存在,而且.NET事件还有更多的问题和限制。为了解决这些问题,或者至少提供一个好的替代方案,我编写了一些可能有用的代码,请查看此文章:http://www.codeproject.com/Articles/864690/Simplifying-Events-in-NET 获取更多信息。 - J. Lennon
@BlueRaja-DannyPflughoeft:C# 6中的空条件运算符使得空值检查更加简单:Click?.Invoke(this, args) - Jon Skeet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接