C#静态事件处理程序与非静态事件处理程序

时间:2016-10-19 10:57:08

标签: events static event-handling non-static

美好的一天!我想了解以下问题:

假设我们有简单的EventSubscriber类

public class EventSubscriber
{
    public static Delegate AddEventHandler(object target, string eventName, Action<object, EventArgs> action)
    {
        EventInfo eventInfo = target.GetType().GetEvent(eventName);
        Delegate handler  = Delegate.CreateDelegate(eventInfo.EventHandlerType, action.Method); 
        eventInfo.AddEventHandler(target, handler);
        return handler;
    }

    public static void RemoveEventHandler(object target, string eventName, Delegate handler)
    {
        var eventInfo = target.GetType().GetEvent(eventName);
        eventInfo.RemoveEventHandler(target, handler);
    }
}

让我们说我们想要订阅Elapsed事件的计时器。

class Program
{
    static System.Timers.Timer timer;
    public static void InitTimer(int interval)
    {
        timer = new System.Timers.Timer(interval);
        timer.Start();
    }
    static void Main(string[] args)
    {
        int interval = 1000;
        InitTimer(interval);
        var handler = EventSubscriber.AddEventHandler(timer, "Elapsed", Handler);
        Thread.Sleep(Convert.ToInt16(interval * 5));
        EventSubscriber.RemoveEventHandler(timer, "Elapsed", handler);
        Thread.Sleep(Convert.ToInt16(interval * 5));
    }

    public static void Handler(object sender, EventArgs args)
    {
        Console.WriteLine("BOOO");
    }
}

现在,如果您编译此应用程序,一切都会正常工作,您将看到应用程序的扩展行为。 让我们在课堂上包装我们的计时器:

public class TimerWrapper
{
    public System.Timers.Timer Timer { get; set; }
    public int Interval { get; set; }
    public TimerWrapper(int interval)
    {
        Interval = interval;
        Timer = new System.Timers.Timer(Interval);
        Timer.Start();
    }
    public static void Handler(object sender, EventArgs args)
    {
        Console.WriteLine("BOOO");
    }
}

现在让我们看一下:

class Program
{
    static void Main(string[] args)
    {
        int interval = 1000;
        TimerWrapper timerWrapper = new TimerWrapper(interval);
        var handler = EventSubscriber.AddEventHandler(timerWrapper.Timer, "Elapsed", TimerWrapper.Handler);
        Thread.Sleep(Convert.ToInt16(interval * 5));
        EventSubscriber.RemoveEventHandler(timerWrapper.Timer, "Elapsed", handler);
        Thread.Sleep(Convert.ToInt16(interval * 5));
    }
}

一切都像以前一样有效。但是如果我们将使TimerWrapper中的处理程序非静态并运行应用程序呢?我们将收到System.ArgumentException,下一条消息“无法绑定到目标方法,因为它的签名或安全透明性与委托类型的不兼容。”

我有假设为什么会如此,但我想要坚定地了解它。

我希望得到全面的答复,提前感谢并感谢您的时间!

1 个答案:

答案 0 :(得分:2)

问题是你正在调用带有重载的Delegate.CreateDelegate,这个重载应该适用于静态方法(或者例如方法调用的目标是额外的委托参数的方法)。 p>

要使其工作,您需要做的就是在创建新委托时传递现有委托的目标:

Delegate handler = Delegate.CreateDelegate(
    eventInfo.EventHandlerType,
    action.Target,
    action.Method); 

如果原始代理人(action)使用的是静态方法,则action.Target已经是null,所以没关系。