我想找出分配了哪些方法来处理控件的事件(来自外部),然后分配相同的方法来处理另一个控件的相同事件。我尝试了以下方法,但没有成功:
private void ReflectMethods(Control control, Control baseControl, string[] excludedEventNames = null, string[] includedEventNames = null)
{
Type baseType = baseControl.GetType();
Type ownType = control.GetType();
foreach (EventInfo baseEventInfo in baseType.GetEvents())
{
if (excludedEventNames != null && excludedEventNames.Contains(baseEventInfo.Name))
continue;
if (includedEventNames != null && !includedEventNames.Contains(baseEventInfo.Name))
continue;
//
// Checking if current control has the same event..
//
foreach (EventInfo ownEventInfo in ownType.GetEvents())
{
if (ownEventInfo.Name == baseEventInfo.Name)
{
FieldInfo eventField = baseType.GetField(baseEventInfo.Name, BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance);
// The above line always returns null, so I cannot get the handler ???
EventHandler eventHandler = (EventHandler)eventField.GetValue(baseControl);
ownEventInfo.AddEventHandler(this, eventHandler);
}
}
}
}
只要您使用的控件由您实现,您的解决方案就很好。发生这种情况是因为编译器为每个事件创建一个字段,您可以像您发布的代码一样访问该字段。但这不是你能做到的唯一方法。这类似于属性:您通常为每个属性都有一个字段,但这不是唯一的方法。
在 Control 的情况下,要获取与事件关联的委托,您必须通过属性 Events 获取 EventHandlerList,然后使用字段的值访问它,该字段的名称由字符串 "Event" 组成,后跟事件的实际名称(例如,对于单击,您必须查找字段"EventClick")。
在这里,您可以找到应适用于 WinForm 控件的代码的修改版本。请注意,它不适用于你自己设计的控件。您应该结合这两种方法来管理所有情况。
private void ReflectMethods(Control control, Control baseControl, string[] excludedEventNames = null, string[] includedEventNames = null)
{
Type baseType = baseControl.GetType();
Type ownType = control.GetType();
EventHandlerList events = typeof(Control).GetProperty("Events", BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static | BindingFlags.NonPublic).GetValue(baseControl, null) as EventHandlerList;
foreach (EventInfo baseEventInfo in baseType.GetEvents())
{
if (excludedEventNames != null && excludedEventNames.Contains(baseEventInfo.Name))
continue;
if (includedEventNames != null && !includedEventNames.Contains(baseEventInfo.Name))
continue;
//
// Checking if current control has the same event..
//
foreach (EventInfo ownEventInfo in ownType.GetEvents())
{
if (ownEventInfo.Name == baseEventInfo.Name)
{
object eventField = typeof(Control).GetField("Event" + baseEventInfo.Name, BindingFlags.NonPublic | BindingFlags.Static).GetValue(baseControl);
Delegate aDel = events[eventField];
ownEventInfo.AddEventHandler(control, aDel);
}
}
}
}