1

我想找出已分配哪些方法来处理控件的事件(从外部),然后分配相同的方法来处理另一个控件的相同事件。我尝试了以下方法但没有成功:

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

1 回答 1

1

只要您使用的控件由您实施,您的解决方案就很好。发生这种情况是因为编译器为您可以访问的每个事件创建了一个字段,就像您发布的代码中一样。但这不是您可以做到的唯一方法。这类似于属性:通常每个属性都有一个字段,但这不是唯一的方法。

在 Control 的情况下,要获取与事件关联的委托,您必须通过属性 Events 获取 EventHandlerList,然后使用名称由字符串“Event”组成的字段的值获取正确的 EventHandler 访问它通过事件的实际名称(例如,对于 Click,您必须查找字段“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);
                }
            }
        }
    }
于 2012-11-14T07:39:12.950 回答