Obtenir le nom de la méthode qui a déclenché une exception

Je connais. Une question similaire a déjà été posée.

  • Comment obtenir le nom de la méthode qui a provoqué l’exception

mais je n’ai pas la solution exacte de cela.

J’ai un événement de clic de bouton dans lequel j’ai une méthode FillCombo() .

Bouton clic événement

 private void button1_Click(object sender, EventArgs e) { try { cmbTemplates.Items.Clear(); lstFiles.Clear(); FillCombo(); } catch (Exception ex) { MethodBase site = ex.TargetSite; Log(ex.ToSsortingng(), site == null ? null : site.Name); } } 

Lors du débogage, j’ai constaté que l’exception se produisait à partir de la méthode FillCombo() . Après cela, j’obtiens la valeur de site.Name comme WinIOError au lieu de FillCombo .

J’ai essayé une autre méthode GetExecutingMethodName() laquelle Chris Gessler a répondu dans Comment obtenir le nom de la méthode à l’origine de la question de l’exception . J’ai donc essayé d’envoyer le nom de la méthode qui a provoqué une exception à l’aide de la méthode GetExecutingMethodName()

 Log(ex.ToSsortingng(), GetExecutingMethodName()); 

Mais j’ai obtenu le résultat comme System.Windows.Forms.Control.OnClick au lieu de FillCombo .

Comment puis-je obtenir le nom réel de la méthode qui a provoqué une exception?

.net prend en charge l’obtention des informations de trace de stack à partir d’une exception. Vous pouvez filtrer la méthode (et son nom) en examinant la première image (origine).

 new StackTrace(ex).GetFrame(0).GetMethod().Name 

Cela vous donnerait probablement exactement le même que le site cible (le win io), mais vous pouvez examiner le stacktrace pour le premier code utilisateur, ou la première image de votre type, ou selon vos besoins.

Par exemple, obtenir le nom du lanceur coupable dans votre assemblage actuel:

 var s = new StackTrace(ex); var thisasm = Assembly.GetExecutingAssembly(); var methodname = s.GetFrames().Select(f => f.GetMethod()).First(m => m.Module.Assembly == thisasm).Name; 

Il est important de comprendre ce que l’on entend par “la méthode qui a jeté l’exception”. Lorsqu’une exception se produit, une méthode spécifique est en cours d’exécution. Le fait que vous ayez appelé votre propre méthode FillCombo() à un moment donné avant l’exception ne signifie pas que c’est la méthode qui a levé l’exception.

La méthode FillCombo() sera toutefois (dans le cas où cela vous importe ici) dans la trace de la stack. C’est pourquoi il est utile de consigner toute la trace de la stack. En effet, je viens généralement de connecter l’ensemble de l’object Exception (c’est-à-dire ex.ToSsortingng() , ou simplement de transmettre l’object exception à ssortingng.Format() ou similaire qui appelle ToSsortingng() pour vous). Cela inclura le type d’exception, le message, la trace entière de la stack et même les informations sur les exceptions internes, le cas échéant.

Le code que vous avez obtenu de l’autre question, pour la méthode GetExecutingMethodName() , n’est pas vraiment utile à GetExecutingMethodName() . Vous remarquerez qu’il s’agit en réalité d’parsingr la trace de stack de l’emplacement d’exécution en cours , en recherchant la première méthode déclarée dans un type autre que celui où GetExecutingMethodName() été déclaré.

Ceci est faux pour votre but pour deux raisons:

  1. Il semble que vous ayez déclaré cette méthode dans la même classe que votre gestionnaire d’événements Click. Cela signifie que la méthode du gestionnaire d’événements est ignorée et vous obtenez donc l’appelant de cette méthode, qui est la méthode Control.OnClick() (c’est-à-dire la méthode qui déclenche réellement l’événement).

Franchement, je trouve cette réponse particulière étrange, car .NET fournit déjà une API permettant de récupérer le MethodInfo de la méthode en cours d’exécution: MethodBase.GetCurrentMethod . Et ceci est bien plus fiable que le code écrit par Chris Gessler.

  1. Plus problématique, vous n’avez pas l’occasion d’appeler cette méthode au moment où l’exception est levée! Au mieux (c.-à-d. Même si vous traitez de la question de l’endroit où la méthode d’assistance est déclarée), tout cet appel qui vous dira est que vous vous trouvez dans votre méthode button1_Click() . Mais vous le savez déjà, car le code que vous écrivez pour gérer l’exception se trouve dans cette méthode.

Si vous voulez connaître le nom de la méthode dans votre méthode en cours d’exécution qui a été appelée avant que l’exception ne se produise, vous pouvez combiner les deux techniques: obtenir le nom de la méthode en cours d’exécution, puis le transmettre à une méthode prenant à la fois et la chaîne de trace de stack de l’object Exception et laissez cette méthode parsingr la chaîne de trace de stack pour rechercher le cadre juste avant la méthode en cours d’exécution dans la trace.

C’est un peu pénible, mais cela pourrait être fait. Voici un exemple de ce à quoi cela pourrait ressembler (programme de console de validation de concept simple):

 static void Main(ssortingng[] args) { try { CallForException(); } catch (Exception e) { Console.WriteLine("Exception occurred calling {0} method", GetCallForExceptionThisMethod(MethodBase.GetCurrentMethod(), e)); } } private static ssortingng GetCallForExceptionThisMethod(MethodBase methodBase, Exception e) { StackTrace trace = new StackTrace(e); StackFrame previousFrame = null; foreach (StackFrame frame in trace.GetFrames()) { if (frame.GetMethod() == methodBase) { break; } previousFrame = frame; } return previousFrame != null ? previousFrame.GetMethod().Name : null; } private static void CallForException() { DoActualException(); } private static void DoActualException() { throw new NotImplementedException(); } 

Enfin, gardez à l’esprit qu’en raison de l’intégration de la méthode et d’autres optimisations, même une trace de stack complète peut comporter des irrégularités, notamment le fait de ne pas avoir le nom réel de la méthode où l’exception a été générée. C’est une autre raison pour laquelle la journalisation de l’intégralité de l’object Exception est généralement beaucoup plus utile. plus il y a de contexte, plus vous avez de chances de pouvoir reconstruire ce qui s’est passé.

Essayez ceci:

 var methodFullName = exception.TargetSite.ReflectedType.FullName