尝试获取与Control事件关联的委托时的问题

时间:2013-05-24 13:50:06

标签: c# winforms reflection

我正在尝试将控件序列化为XML,我想序列化他们的事件处理程序。

我正在使用这段代码:

Control childCtrl = ....

if (childCtrl.GetType() == typeof(Button)) {
    EventInfo baseEventInfo = childCtrl.GetType().GetEvent("Click");

    EventHandlerList events =
        typeof(Control).GetProperty("Events",
                                    BindingFlags.Instance |
                                    BindingFlags.Public   |
                                    BindingFlags.Static   |
                                    BindingFlags.NonPublic).GetValue(childCtrl, null)
                                      as EventHandlerList;
    object eventField = typeof(Control).GetField("Event" + baseEventInfo.Name,
                                                 BindingFlags.NonPublic |
                                                 BindingFlags.Static).GetValue(childCtrl);
    Delegate aDel = events[eventField];

    xmlSerialisedForm.WriteElementString("Click", aDel.Method.ToString());
}

if (childCtrl.GetType() == typeof(CheckBox)) {
    EventInfo baseEventInfo = childCtrl.GetType().GetEvent("CheckedChanged");

    EventHandlerList events =
      typeof(Control).GetProperty("Events",
                                  BindingFlags.Instance |
                                  BindingFlags.Public   |
                                  BindingFlags.Static   |
                                  BindingFlags.NonPublic).GetValue(childCtrl, null)
                                    as EventHandlerList;
    //Error here: GetField returns null
    object eventField = typeof(Control).GetField("Event" + baseEventInfo.Name,
                                                 BindingFlags.NonPublic |
                                                 BindingFlags.Static).GetValue(childCtrl);
    Delegate aDel = events[eventField];
    xmlSerialisedForm.WriteElementString("CheckedChanged", aDel.Method.ToString());
}

现在我知道该复选框有一个绑定事件CheckedChanged的处理程序;使用调试器时,我可以在EventHandlerList

中看到该方法

Enter image description here

现在,当处理Button时,相同的代码实际上有效(当我想让代理与Click事件相关联时)。为什么它不适用于CheckBox?我在这里缺少什么?

编辑:我当前的解决方法(非常难看)是我在GetFields上调用typeof(CheckBox)并查看数组中推断出来的:

if (childCtrl.GetType() == typeof(CheckBox)) {
    EventHandlerList events =
      typeof(Control).GetProperty("Events",
                                  BindingFlags.Instance |
                                  BindingFlags.Public   |
                                  BindingFlags.Static   |
                                  BindingFlags.NonPublic).GetValue(childCtrl, null)
                                    as EventHandlerList;

    object eventField =
      typeof(CheckBox).GetFields(BindingFlags.NonPublic |
                                 BindingFlags.Static)[0].GetValue(childCtrl);
    Delegate aDel = events[eventField];
    xmlSerialisedForm.WriteElementString("CheckedChanged", aDel.Method.ToString());
}

1 个答案:

答案 0 :(得分:2)

相当令人愤怒的是,CheckedChanged事件似乎以与.NET框架上其他事件完全不同的方式编写。 CheckStateChanged也是如此。他们在这里。

typeof(CheckBox).GetField("EVENT_CHECKEDCHANGED",
      BindingFlags.NonPublic | 
      BindingFlags.Static| 
      BindingFlags.Instance | 
      BindingFlags.FlattenHierarchy);
typeof(CheckBox).GetField("EVENT_CHECKSTATECHANGED", 
      BindingFlags.NonPublic |
      BindingFlags.Static|
      BindingFlags.Instance |
      BindingFlags.FlattenHierarchy);

只是为了让它变得更加特别,你不能将所有内容都视为CheckBox,或者这是你将获得的唯一两件事。