Определить список обработчиков событий, связанных с событием - PullRequest
29 голосов
/ 19 марта 2009

У меня есть форма WinForms, которая не закрывается. В OnFormClosing e.Cancel имеет значение true. Я предполагаю, что какой-то объект в моем приложении привязан к событию Closing или FormClosing и блокирует закрытие. Чтобы выяснить, я бы хотел определить, какие делегаты связаны с одним из этих событий.

Есть ли способ определить список обработчиков, связанных с событием? В идеале я хотел бы сделать это через отладчик Visual Studio, но могу написать код в приложении, чтобы найти обработчики, если это необходимо. Понимая, что событие похоже на скрытое приватное поле, я перешел через отладчик к «непубличным полям» для предка «Windows.Forms.Form» моей формы, но безрезультатно.

Ответы [ 2 ]

32 голосов
/ 19 марта 2009

Короче говоря, вы не должны это делать - но для целей отладки ...

Событие часто поддерживается частным полем - но не с элементами управления; они используют подход EventHandlerList. Вам нужно было бы получить доступ к защищенному элементу Events формы, чтобы найти объект, сопоставленный с (частным) объектом EVENT_FORMCLOSING.

Если у вас есть 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);
        }
    }
}
1 голос
/ 26 июня 2009

Возможно, проблема в том, что форма не проверяется.

Событие FormClosing вызывается закрытым методом WmClose в Form, который инициализирует e.Cancel в !Validate(true). Я не исследовал, но при определенных обстоятельствах Validate всегда будет возвращать false, вызывая отмену закрытия независимо от каких-либо обработчиков событий.

Чтобы исследовать это, включите .Net отладку источника , установите точку останова в обработчике FormClosing, перейдите к источнику для Form.WmClose (вверх по стеку вызовов), поместите точку останова в начале WmClose и закройте форму снова. Затем просмотрите его в отладчике и посмотрите, почему Validate возвращает false. (Или какой обработчик событий устанавливает e.Cancel в true)

Чтобы решить эту проблему, установите e.Cancel в false в своем собственном обработчике.

...