Determina l’elenco dei gestori di eventi associati all’evento

Ho un modulo WinForms che non verrà chiuso. In OnFormClosing, e.Cancel è impostato su true. Sto indovinando che alcuni oggetti nella mia applicazione sono legati all’evento Closing o FormClosing e stanno bloccando la chiusura. Per scoprirlo, vorrei determinare quali delegati sono legati a uno di questi eventi.

C’è un modo per determinare l’elenco dei gestori associati a un evento? Idealmente lo farei tramite il debugger di Visual Studio, ma posso scrivere il codice nell’applicazione per trovare i gestori, se necessario. Capendo che un evento è come un campo privato nascosto, ho navigato attraverso il Debugger verso i “Campi non pubblici” per l’antenato “Windows.Forms.Form” del mio modulo, ma senza risultato.

In breve, non sei obbligato a farlo, ma a scopo di debug …

Un evento è spesso supportato da un campo privato – ma non con i controlli; usano l’approccio EventHandlerList . Dovresti accedere al membro degli Events protetti del modulo, cercando l’object mappato all’object EVENT_FORMCLOSING (privato).

Una volta che hai FormClosingEventHandler , GetInvocationList dovrebbe fare il lavoro.


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

Il problema potrebbe essere che il modulo non convalida.

L’evento FormClosing viene generato dal metodo WmClose privato in Form , che inizializza e.Cancel to !Validate(true) . Non ho indagato, ma in alcune circostanze, Validate restituirà sempre false , causando la chiusura da annullare indipendentemente da eventuali gestori di eventi.

Per indagare su questo, abilitare il debug di origine .Net , inserire un punto di interruzione nel gestore FormClosing , andare al sorgente per Form.WmClose (sopra lo stack di chiamate), inserire un punto di interruzione all’inizio di WmClose e chiudere nuovamente il modulo. Quindi, passalo attraverso il debugger e scopri perché Validate sta restituendo false . (O quale gestore di eventi sta impostando e.Cancel su true)

Per risolvere il problema, imposta e.Cancel su false nel tuo gestore.