2016-10-19 215 views
0

美好的一天!我想了解以下问题:C#静态事件处理程序与非静态事件处理程序

比方说,我们有简单的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中的处理程序处于非静态并运行应用程序呢?我们将接收System.ArgumentException,并显示下一条消息“无法绑定到目标方法,因为它的签名或安全透明度与代理类型的兼容性不兼容。”

我有假设为什么这样,但我想知道它坚定。

我希望能得到全面的答案,在此先感谢并感谢您的时间!

+0

我没有看到你给出的代码的例外。你确定你可以用*代码来重现它吗? –

+0

你做了最后一步吗?我的意思是在TimerWrapper中的Handler必须是非静态方法。 – Crispried

+0

啊,我错过了。如果你真的显示不起作用的代码,而不是仅仅两个* do *工作的例子,那真的很有帮助。当我有机会时会再试一次。 –

回答

2

问题是你打电话给Delegate.CreateDelegate带有一个预计适用于静态方法的重载(或者例如有一个额外的委托参数是方法调用目标的方法)。

所有你需要做的就是它的工作是通过在现有委托的目标,当您创建新的一个:

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

如果原来的委托(action)使用静态方法, action.Target已经是null,所以没关系。

+0

非常感谢,谢谢! – Crispried