web-dev-qa-db-fra.com

Récupération du nom de la méthode appelante à partir d'une méthode

Duplicata possible:
Comment puis-je trouver la méthode qui a appelé la méthode actuelle?

J'ai une méthode dans un objet qui est appelée à partir d'un certain nombre d'endroits au sein de 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.

EXEMPLE de pseudo-code:

public Main()
{
     PopularMethod();
}

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

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

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

Dans PopularMethod() j'aimerais voir la valeur de Main si elle était appelée depuis Main ... j'aimerais voir "ButtonClick" si PopularMethod() a été appelée depuis ButtonClick

Je regardais la System.Reflection.MethodBase.GetCurrentMethod() mais cela ne me donnera pas la méthode d'appel. J'ai regardé la classe StackTrace mais je n'ai vraiment pas aimé exécuter une trace de pile entière chaque fois que cette méthode est appelée.

55
Scott Vercuski

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.

71
jason

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

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

Le compilateur ajoute automatiquement le nom de l'appelant; alors:

void Foo() {
    PopularMethod();
}

passera dans "Foo".

147
Marc Gravell

C'est vraiment très simple.

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

Mais soyez prudent, je suis un peu sceptique quant à savoir si l'inclusion de la méthode a un effet. Vous pouvez le faire pour vous assurer que le compilateur JIT ne 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();
}
16
John Leidegren

Passez simplement un paramètre

public void PopularMethod(object sender)
{

}

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

5
Sruly

J'ai souvent trouvé que je voulais faire ça, mais je finis toujours par refactoriser la conception de mon système, donc je n'ai pas cet anti-modèle "Queue qui remue le chien". Le résultat a toujours été une architecture plus robuste.

4
JonPen

Bien que vous puissiez certainement tracer la pile et la comprendre de cette façon, je vous exhorte à repenser votre conception. Si votre méthode a besoin de connaître une sorte d '"état", je dirais simplement créer une énumération ou quelque chose, et prendre cela comme paramètre dans votre PopularMethod (). Quelque chose dans ce sens. Sur la base de ce que vous publiez, tracer la pile serait exagéré OMI.

1
BFree

Je pense que vous devez utiliser la classe StackTrace puis StackFrame.GetMethod() sur l'image suivante.

Cela semble étrange d'utiliser Reflection pour le moment. Si vous définissez PopularMethod, vous ne pouvez pas aller définir un paramètre ou quelque chose pour transmettre les informations que vous voulez vraiment. (Ou mettre sur une classe de base ou quelque chose ...)

0
C. Dragon 76