【问题标题】:Issue when trying to get the delegate associated to a Control's event尝试获取与控件事件关联的委托时出现问题
【发布时间】:2013-05-24 13:50:06
【问题描述】:

我正在尝试将控件序列化为 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 中看到该方法:

现在,在处理 Button 时,相同的代码实际上可以工作(当我想获得与 Click 事件关联的委托时)。为什么它不适用于 CheckBox?我在这里错过了什么?

编辑:我通过在typeof(CheckBox) 上调用GetFields 并查看数组推断出我当前的解决方法(非常丑陋):

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

【问题讨论】:

    标签: c# winforms reflection


    【解决方案1】:

    更令人恼火的是,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,否则您将获得仅有的两个事件。

    【讨论】:

      猜你喜欢
      • 2013-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-26
      相关资源
      最近更新 更多