C# 确定绑定到事件的事件处理程序列表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/660480/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 12:17:33  来源:igfitidea点击:

Determine list of event handlers bound to event

c#visual-studio-2008debuggingevents

提问by JoshL

I have a WinForms form that won't close. In OnFormClosing, e.Cancel is set to true. I am guessing that some object in my application has bound to the Closing or FormClosing event, and is blocking the close. To find out, I'd like to determine what delegates are bound to one of these events.

我有一个无法关闭的 WinForms 表单。在 OnFormClosing 中,e.Cancel 设置为 true。我猜我的应用程序中的某个对象已绑定到 Closing 或 FormClosing 事件,并且正在阻止关闭。为了找出答案,我想确定哪些代表绑定到这些事件之一。

Is there a way to determine the list of handlers bound to an event? Ideally I would do this via the Visual Studio debugger, but can write code in the application to find the handlers if necessary. Understanding that an event is like a hidden private field, I've navigated through the Debugger to the "Non-Public Fields" for the "Windows.Forms.Form" ancestor of my form, but to no avail.

有没有办法确定绑定到事件的处理程序列表?理想情况下,我会通过 Visual Studio 调试器执行此操作,但可以在应用程序中编写代码以在必要时查找处理程序。了解事件就像一个隐藏的私人字段,我已经通过调试器导航到我的表单的“Windows.Forms.Form”祖先的“非公共字段”,但无济于事。

采纳答案by Marc Gravell

In short, you're not meant to do this - but for debugging purposes...

简而言之,您不打算这样做-而是出于调试目的...

An event is oftenbacked by a private field - but not with controls; they use the EventHandlerListapproach. You would have to access the form's protected Eventsmember, looking for the object mapped to the (private) EVENT_FORMCLOSING object.

事件通常由私有字段支持 - 但没有控件;他们使用这种EventHandlerList方法。您必须访问表单的受保护Events成员,查找映射到(私有)EVENT_FORMCLOSING 对象的对象。

Once you have the FormClosingEventHandler, GetInvocationListshould do the job.

一旦你有了FormClosingEventHandler,就GetInvocationList应该完成这项工作。



using System;
using System.ComponentModel;
using System.Reflection;
using System.Windows.Forms;
class MyForm : Form
{
    public MyForm()
    { // assume we don't know this...
        Name = "My Form";
        FormClosing += Foo;
        FormClosing += Bar;
    }

    void Foo(object sender, FormClosingEventArgs e) { }
    void Bar(object sender, FormClosingEventArgs e) { }

    static void Main()
    {
        Form form = new MyForm();
        EventHandlerList events = (EventHandlerList)typeof(Component)
            .GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance)
            .GetValue(form, null);
        object key = typeof(Form)
            .GetField("EVENT_FORMCLOSING", BindingFlags.NonPublic | BindingFlags.Static)
            .GetValue(null);

        Delegate handlers = events[key];
        foreach (Delegate handler in handlers.GetInvocationList())
        {
            MethodInfo method = handler.Method;
            string name = handler.Target == null ? "" : handler.Target.ToString();
            if (handler.Target is Control) name = ((Control)handler.Target).Name;
            Console.WriteLine(name + "; " + method.DeclaringType.Name + "." + method.Name);
        }
    }
}

回答by SLaks

The problem might be that the form doesn't validate.

问题可能是表单未验证。

The FormClosingevent is raised by the private WmClosemethod in Form, which initializes e.Cancelto !Validate(true). I haven't investigated, but in certain circumstances, Validatewill always return false, causing the close to be canceled regardless of any event handlers.

FormClosing事件由WmClosein的私有方法引发,该方法Form初始化e.Cancel!Validate(true)。我没有调查过,但在某些情况下,Validate将始终 return false,导致关闭被取消,而不管任何事件处理程序。

To investigate this, enable .Net source debugging, put a breakpoint in your FormClosinghandler, go to the source for Form.WmClose(up the call stack), put a breakpoint at the beginning of WmClose, and close the form again. Then, step through it in the debugger and see why Validateis returning false. (Or which event handler is setting e.Cancelto true)

要对此进行调查,请启用.Net 源代码调试,在FormClosing处理程序中放置一个断点,转到Form.WmClose(调用堆栈上方)的源代码,在 的开头放置一个断点WmClose,然后再次关闭表单。然后,在调试器中逐步执行它,看看为什么Validate返回false. (或者哪个事件处理程序设置e.Cancel为 true)

To solve the problem, set e.Cancelto falsein your own handler.

要解决此问题,e.Cancelfalse在您自己的处理程序中设置为。