2011-03-28 82 views
4

我正在嘗試訂閱所有由類似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類類型。

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

------------後編輯--------- 在所有三種情況下(我的嘗試,ds27680的建議和托馬斯萊維斯克的建議),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的類型是什麼使得它失敗...

回答

2

你可以嘗試:

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; 
} 

當然有很多的錯誤檢查/處理缺少的...

+0

就像我最初的嘗試:System.Reflection.TargetException:{「對象不符合目標類型。」} – 2011-03-28 10:46:30

+0

@Andrei Rinea這很奇怪,我測試了一個WPF應用程序和一個網格控件,它的工作原理... – ds27680 2011-03-28 10:55:33

+0

@Andrei Rinea:它可以是你使用的自定義控件有一些不遵循(object sender,EventArgs args)模式的自定義事件嗎?你有沒有嘗試過使用標準的WPF控件?您可以嘗試在getEventArgsType方法中追蹤每個事件的參數數量和類型... – ds27680 2011-03-28 11:01:46

1

您需要委託 「轉換」 爲適當的類型:

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); 
} 
+0

就像我的初步嘗試:System.Reflection.TargetException:{「對象不匹配目標類型」} – 2011-03-28 10:36:59

+0

我嘗試過了,它對我來說工作得很好...無論如何,這不像你的代碼:你試圖直接訂閱處理程序,而不改變代理類型 – 2011-03-28 11:38:42

+0

是的,問題,因爲我告訴ds27680,是來自控制。它有不遵循(object sender,EventArgs args)模式的事件。 – 2011-03-28 11:40:57

相關問題