60 votes

Récupération du nom de la méthode appelante à l'intérieur d'une méthode

J'ai une méthode dans un objet qui est appelée à partir d'un certain nombre d'endroits dans l'objet. Existe-t-il un moyen rapide et facile d'obtenir le nom de la méthode qui a appelé cette méthode populaire ?

Pseudo Code EXEMPLE :

public Main()
{
     PopularMethod();
}

public ButtonClick(object sender, EventArgs e)
{
     PopularMethod();
}

public Button2Click(object sender, EventArgs e)
{
     PopularMethod();
}

public void PopularMethod()
{
     //Get calling method name
}

Sur PopularMethod() Je voudrais voir la valeur de Main s'il a été appelé depuis Main ... J'aimerais voir " ButtonClick " si PopularMethod() a été appelé à partir de ButtonClick

Je regardais le System.Reflection.MethodBase.GetCurrentMethod() mais cela ne me permet pas d'obtenir la méthode d'appel. J'ai regardé le StackTrace mais je n'avais vraiment pas envie de lancer un suivi de pile complet à chaque fois que cette méthode est appelée.

180voto

Marc Gravell Points 482669

Dans .NET 4.5 / C# 5, c'est simple :

public void PopularMethod([CallerMemberName] string caller = null)
{
     // look at caller
}

El compilateur ajoute automatiquement le nom de l'appelant ; ainsi :

void Foo() {
    PopularMethod();
}

passera dans "Foo" .

4 votes

Quelles sont les conséquences de cette solution sur les performances ?

7 votes

@Feckmore aucun : le compilateur l'ajoute comme un littéral lors de la compilation. Ce sera beaucoup plus rapide que de regarder la StackTrace, etc. En fait, il est compilé comme PopularMethod("CurrentMethodName").

0 votes

Je reçois une erreur disant Impossible de trouver CallerMemberName. VS Express C# 2010

76voto

Jason Points 125291

Je ne pense pas que cela puisse être fait sans tracer la pile. Cependant, il est assez simple de le faire :

StackTrace stackTrace = new StackTrace();
MethodBase methodBase = stackTrace.GetFrame(1).GetMethod();
Console.WriteLine(methodBase.Name); // e.g.

Cependant, je pense que vous devez vraiment vous arrêter et vous demander si cela est nécessaire.

0 votes

4 votes

System.Diagnostics est l'espace de nom de StackTrace, System.Reflection est l'espace de nom de MethodBase.

0 votes

Jason - Merci, je ne suis pas sûr que la méthode "StackTrace" soit très gourmande en ressources, mais cela me permet d'obtenir ce que je cherche. Il s'agit juste d'un bloc de code de débogage pour moi, il ne sera pas mis en production. Merci encore pour votre aide !

16voto

John Leidegren Points 21951

C'est en fait très simple.

public void PopularMethod()
{
    var currentMethod = System.Reflection.MethodInfo
        .GetCurrentMethod(); // as MethodBase
}

Mais attention, je suis un peu sceptique quant à l'effet de l'inlining sur la méthode. Vous pouvez le faire pour vous assurer que le compilateur JIT ne vous gênera pas.

[System.Runtime.CompilerServices.MethodImpl(
 System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
public void PopularMethod()
{
    var currentMethod = System.Reflection.MethodInfo
        .GetCurrentMethod();
}

Pour obtenir la méthode d'appel :

[System.Runtime.CompilerServices.MethodImpl(
 System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
public void PopularMethod()
{
    // 1 == skip frames, false = no file info
    var callingMethod = new System.Diagnostics.StackTrace(1, false)
         .GetFrame(0).GetMethod();
}

3 votes

John Leidgren - Cela me donnera le nom "PopularMethod", mais je veux le nom de la méthode qui a appelé PopularMethod.

1 votes

D'accord, alors la trace de la pile est ce dont vous avez besoin. J'ai mal interprété votre question.

0 votes

Il suffit d'utiliser .GetFrame(1) à la place, non ?

5voto

Sruly Points 3361

Il suffit de passer un paramètre

public void PopularMethod(object sender)
{

}

IMO : Si c'est assez bon pour les événements, ça devrait être assez bon pour ça.

0 votes

Sruly - Oui c'est définitivement une option, j'essayais de le faire sans modifier l'appel de la méthode. Ce serait mon dernier recours.

0 votes

À moins que vous ne l'exposiez en tant qu'API publique, pourquoi se donner la peine d'utiliser la réflexion si vous pouvez le faire de cette manière ? Rappelez-vous KISS

0 votes

C'est la MEILLEURE réponse, n'utilisez pas la réflexion ou d'autres trucs, identifiez l'appelant via un paramètre.

4voto

JonPen Points 39

J'ai souvent eu envie de le faire, mais j'ai toujours fini par remanier la conception de mon système afin d'éviter l'anti-modèle "Tail wagging the dog". Le résultat a toujours été une architecture plus robuste.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X