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

本文关键字:程序 事件处理 静态 | 更新日期: 2023-09-27 18:13:39

大家好!我想了解以下问题:

假设我们有一个简单的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);
    }
}

假设我们有一个计时器我们想订阅流逝事件

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非静态和运行应用程序呢?我们将收到系统。无法绑定到目标方法,因为其签名或安全透明度与委托类型的签名或安全透明度不兼容。

我有一些猜想,但我想确切地知道为什么会这样。

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

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

问题是,你调用Delegate.CreateDelegate与一个过载,预计工作的静态方法(或例如方法,有一个额外的委托参数,这是方法调用的目标)。

要让它工作,你所需要做的就是在创建新委托时传递现有委托的目标:

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

如果原始委托(action)使用静态方法,action.Target将已经是null,所以这是好的