我正在尝试订阅由类似WPF GridView的第三方组件公开的 ALL 事件,以便进行一些调试。除了建议这可能不是调试它的最佳方式和类似的东西,我想知道是否可以这样做。
对于路由事件,它的工作原理如下:
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类型完全不匹配的事实是它失败的原因......
答案 0 :(得分:3)
您需要将委托“转换”为适当的类型:
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);
}
答案 1 :(得分:2)
您可以使用Delegate.CreateDelegate构建特定类型的事件。值得一试。
答案 2 :(得分: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;
}
当然缺少很多错误检查/处理......