简单情况(VS2005,.NET2):I have a textBox1 on a panel1. I need to track all the emitted events from this textBox1.
实际上,当我需要从这个textBox1跟踪单个事件(例如TextChanged)时,我向(TextChanged事件)添加了一个处理程序,然后我设置了一个写入的非阻塞 breackpoint 输出控制台包含函数(eventhandler)名称的消息。 因此,对于单个事件,我可以编写此处理程序并设置breackpoint,但是我可以为所有可能的文本框(或其他控件)的事件执行类似的操作吗?
alt text http://lh5.ggpht.com/_1TPOP7DzY1E/S0H5NHjXSjI/AAAAAAAAC24/tV0IiUsxwAU/s800/eventsTrack.png
更深入的是,我需要知道在上述控件(textBox)的某个时刻发生了什么事件。
感谢。
答案 0 :(得分:3)
Aviad的帖子是一个好的开始。您可以将其用于EventHandler
类型的事件。对于其他委托类型,您可以使用相同的技术手动为每种类型创建处理程序。
如果您想要更灵活,您应该使用System.Reflection.Emit
在运行时创建事件处理程序。以下是详细说明:http://msdn.microsoft.com/en-us/library/ms228976.aspx。向下滚动到“使用动态方法在运行时生成事件处理程序”标题。
<强> //修改
我创建了一个简单的类,它能够处理特定对象的所有事件并将它们传递给通用事件处理程序。代码基于Microsoft和XTreme.NET Talk的示例。
基本理念
<强>用法强>
要附加的对象在构造函数中传递。下一个UniversalEventHandler
类型的匿名方法用于处理所有事件。此方法在eventName
中接收事件名称args
和事件参数。您可以在此方法上设置断点并在Visual Studio中检查参数或自行打印它们。在此示例用法中,仅打印事件名称,可在“输出”窗口中找到(菜单视图&gt; Visual Studio中的输出)。在此示例中,将检查标准按钮button1
。
private void Form1_Load(object sender, EventArgs e)
{
UniversalEventHandler handler = (UniversalEventHandler) delegate(string eventName, object[] args)
{
System.Diagnostics.Trace.WriteLine(eventName);
};
EventInspector inspector = new EventInspector(button1, handler);
}
<强>代码强>
public delegate void UniversalEventHandler(string eventName, object[] args);
public class EventInspector
{
private UniversalEventHandler eventHandler;
private object srcObject;
public EventInspector(object srcObject, UniversalEventHandler eventHandler)
{
this.eventHandler = eventHandler;
this.srcObject = srcObject;
Attach();
}
public void EventReceived(string eventName, object[] args)
{
if (eventHandler != null)
eventHandler(eventName, args);
}
public void Attach()
{
Type type = srcObject.GetType();
EventInfo[] srcEvents = type.GetEvents();
for (int i = 0; i < srcEvents.Length; i++)
{
EventInfo srcEvent = srcEvents[i];
Type[] parameterTypes = GetDelegateParams(srcEvent.EventHandlerType);
DynamicMethod handler = new DynamicMethod("", typeof(void), parameterTypes, typeof(EventInspector));
string name = srcEvent.Name;
ILGenerator il = handler.GetILGenerator();
il.DeclareLocal(typeof(object[]));
il.DeclareLocal(typeof(string));
il.Emit(OpCodes.Ldstr, srcEvent.Name);
il.Emit(OpCodes.Stloc_1);
il.Emit(OpCodes.Ldc_I4, parameterTypes.Length - 1);
il.Emit(OpCodes.Newarr, typeof(object));
il.Emit(OpCodes.Stloc_0);
for (int j = 0; j < parameterTypes.Length - 1; j++)
{
Type parameter = parameterTypes[j];
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldc_I4, j);
il.Emit(OpCodes.Ldarg, j + 1);
il.Emit(OpCodes.Stelem_Ref);
}
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Ldloc_0);
MethodInfo eventReceivedMethod = this.GetType().GetMethod("EventReceived", BindingFlags.Public | BindingFlags.Instance);
il.EmitCall(OpCodes.Callvirt, eventReceivedMethod, null);
il.Emit(System.Reflection.Emit.OpCodes.Ret);
srcEvent.AddEventHandler(srcObject, handler.CreateDelegate(srcEvent.EventHandlerType, this));
}
}
private Type[] GetDelegateParams(Type d)
{
MethodInfo delegateMethod = d.GetMethod("Invoke");
ParameterInfo[] delegateParams = delegateMethod.GetParameters();
Type[] result = new Type[delegateParams.Length + 1];
result[0] = this.GetType();
for (int i = 0; i < delegateParams.Length; i++)
{
result[i + 1] = delegateParams[i].ParameterType;
}
return result;
}
}
答案 1 :(得分:1)
您可以使用反射来获取对象的所有事件,并将它们全部挂钩到您的调试方法中。
void HookAllEvents(object obj)
{
foreach (var evInfo in obj.GetType().GetEvents())
{
evInfo.AddEventHandler(obj, new EventHandler(DebugEventHandler));
}
}
void DebugEventHandler(object sender, EventArgs e)
{
}
不要忘记在最后解开:)
答案 2 :(得分:0)
您不能自动执行此操作。
但是,如果您只想弄清楚哪些事件会被解雇,请尝试使用Spy ++。