簡體   English   中英

如何以編程方式訂閱對象的所有事件?

[英]How can I programmatically subscribe to all the events of an object?

我試圖訂閱由類似WPF GridView的第三方組件公開的所有事件,以便進行一些調試。 除了建議這可能不是調試它的最佳方式和類似的東西,我想知道是否可以這樣做。

對於路由事件,它的工作原理如下:

var type = tree.GetType();
do
{
    var staticFields = type.GetFields(BindingFlags.Static | BindingFlags.Public);
    foreach (var staticField in staticFields)
    {
        if (typeof(RoutedEvent).IsAssignableFrom(staticField.FieldType))
        {
            tree.AddHandler((RoutedEvent)staticField.GetValue(null), new RoutedEventHandler(OnRoutedEvent), true);
        }
    }
} while ((type = type.BaseType) != typeof(object)/* && type.FullName.StartsWith("Telerik")*/);

public void OnRoutedEvent(object sender, System.Windows.RoutedEventArgs e)
{
    Debug.WriteLine(e.RoutedEvent.ToString());
}

但是,對於典型事件,這似乎不起作用:

var evts = tree.GetType().GetEvents();
foreach (var ev in evts)
{
    ev.AddEventHandler(this, new EventHandler(OnEvent));
}

public void OnEvent(object sender, EventArgs e)
{
      //..
}

因為它不喜歡委托是EventHandler而不是特殊類型,或者因為事件處理程序方法的簽名不包含專門的EventArgs類類型。

這可以以某種方式完成嗎?

------------ LATER EDIT ---------在所有這三種情況下(我的嘗試,ds27680的建議和Thomas Levesque的建議),AddEventHandler調用失敗了:

        System.Reflection.TargetException occurred
            Message=Object does not match target type.
            Source=mscorlib
                StackTrace:
                   at System.Reflection.RuntimeMethodInfo.CheckConsistency(Object target)
                   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
                   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
                   at System.Reflection.EventInfo.AddEventHandler(Object target, Delegate handler)
                   at Test.MainWindow..ctor() in c:\users\me\documents\visual studio 2010\Projects\Test\Test\MainWindow.xaml.cs:line 39

我想事件處理程序方法的簽名與EventArgs類型完全不匹配的事實是它失敗的原因......

您需要將委托“轉換”為適當的類型:

var evts = tree.GetType().GetEvents();
EventHandler tmp = OnEvent;
foreach (var ev in evts)
{
    Delegate handler = Delegate.CreateDelegate(ev.EventHandlerType, tmp.Target, tmp.Method);
    ev.AddEventHandler(this, handler);
}

您可以使用Delegate.CreateDelegate構造特定類型的事件。 值得一試。

你可以嘗試:

public class DebugHook
{
    public static void OnEvent<EventArgsType>(object sender, EventArgsType eventArgs)
    {

    }
}

然后:

foreach (var ev in evts)
{
   Type argsType = getEventArgsType(ev);

   MethodInfo hook = typeof(DebugHook).GetMethod("OnEvent");
   MethodInfo boundEventhandler = hook.MakeGenericMethod(new [] { argsType} );

   Delegate handler = Delegate.CreateDelegate(ev.EventHandlerType, boundEventhandler);

   ev.AddEventHandler(this, handler );
}

其中getEventArgs如下所示:

 public Type getEventArgsType(EventInfo eventType)
 {
     Type t = eventType.EventHandlerType;
     MethodInfo m = t.GetMethod("Invoke");

     var parameters = m.GetParameters();
     return parameters[1].ParameterType;
 }

當然很多錯誤檢查/處理都丟失了......

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM