2016-05-20 8 views
0

Ich versuche, den allerersten Methodennamen zu erhalten, der mehrere Methodenaufrufe paraphiert hat.Wie finden Sie den übergeordneten Methodennamen in mehreren Untermethoden in C#?

ich zum Beispiel die unten haben,

static void Main(string[] args) 
    { 
     Test1(); 
    } 

    static void Test1() 
    { 
     Test2(); 
    } 
    static void Test2() 
    { 
     Console.WriteLine("Soemthing"); 
    } 

Im Test2 Methode, ich brauche die wichtigste Methode wissen hat diese Kette initiiert. Ich habe versucht, mit dem StackTrace und Reflection wie folgt.

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

aber die stackTrace.getFrame (1) ist nicht das, was ich erwarte. Es wird mir die vorherige Methode geben, die Test1 ist.

Ich möchte den Wert getFrame nicht fest auf codieren, um die Main-Methode zu erhalten.

Gibt es eine Möglichkeit, die übergeordnete Methode von einer der Untermethoden zu erhalten, ohne den Frame-Wert hart zu codieren?

+0

Wenn Sie es tun wollen manuell können Sie rechts auf der Methode klicken Sie dann auf Gehe zu Deifnition klicken oder Peek Definition und halten allerdings so, bis Sie die Eltern finden, die Sie wollen. Aber automatisch bin ich nicht sicher – Brendon

+4

Was sind Ihre Kriterien für "die ursprüngliche Methode"? In einer einzigen Thread-Konsole-Anwendung ist es immer "Main", keine Notwendigkeit, es zu bestimmen ... in einem Web-Service, können Sie durch die IIS-Baugruppen krabbeln ... –

+0

Ich tat dies nur für die Forschung. Aber letztendlich werden wir dies mit einem MVC 6 WebAPi verwenden. @ RenéVogt –

Antwort

2

Dies wird tun, was Sie wollen:

var stackTrace = new StackTrace(); 
string lastCSharpMethodName = null; 
for (int i = 0;; i++) 
{ 
    if (stackTrace.GetFrame(i).GetILOffset() == StackFrame.OFFSET_UNKNOWN) 
     break; 

    lastCSharpMethodName = stackTrace.GetFrame(i).GetMethod().Name; 
} 

Console.WriteLine(lastCSharpMethodName); 

Wenn Sie genau an dem Debugger in VS schauen, sehen Sie, dass die erste Methode für eine Konsolenanwendung aufgerufen (als Beispiel) ist das native mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() die als Unknown in Abschnitt Sprache gekennzeichnet ist:

enter image description here .

Was der obige Code tut, ist die unknown herausfiltern und die erste bekannte Zeile (siehe: https://msdn.microsoft.com/en-us/library/system.diagnostics.stackframe.getiloffset(v=vs.110).aspx).

, die Ihr Fall ist Main()

+0

Dies gibt mir die Antwort, die ich will. Aber ich versuche einen Weg zu finden, dies ohne die Schleife zu tun. Auch ich werde dies ein WebApi anwenden und sehen, was passieren wird. Danke. –

+0

Es funktioniert auch mit dem WebApi. :) Jetzt einen Weg finden, es ohne die Schleife zu tun. –

+0

Froh, es zu hören. Ich bin mir nicht sicher, ob es einen Weg gibt, es ohne die Schleife zu machen, aber viel Glück für Sie. – kha

0

Ich denke, Sie suchen nicht nach dem ersten Frame auf Ihrem Stapel, aber der letzte.

StackTrace stackTrace = new StackTrace(); 
MethodBase methodBase = stackTrace.GetFrame(stackTrace .FrameCount - 1).GetMethod(); // Not sure about the "- 1" 
Console.WriteLine(methodBase.Name); 

Allerdings, wenn ich mich gut erinnere, etwas mit dem Stapel Anruf ist, der den Stapel für die nächsten Anrufe schneiden: Mit dem FrameCount Eigenschaft, könnte man so etwas schreiben. (Sie sollten die vorherigen Methodenaufrufe nicht sehen können, wenn Sie einen zweiten Aufruf auf dem Stapel ausführen.)

Aber da bin ich mir nicht sicher.

+0

Ja @ romain-aga es gab mir auch "ThreadStart" –

+0

Sie können stattdessen "- 2" verwenden. Aber es wird nur für diesen Fall funktionieren. Vielleicht müssen Sie den ganzen Stapel durchsuchen, bis Sie den ThreadStart oder das Ende erreichen, und speichern Sie das vorherige Element, um zu finden, nach was Sie suchen. –

0

können Sie diese Methode verwenden, um die Namen der Methode oben (oder besser unten) des Call-Stack zu bestimmen:

private static string GetInitialCaller() 
{ 
    StackTrace trace = new StackTrace(); 
    StackFrame frame = trace.GetFrames()?.LastOrDefault(); 
    return frame?.GetMethod()?.Name; 
} 

es in einer Konsolenanwendung getestet, wie die

private static void TestIt() 
{ 
    string caller = GetInitialCaller(); 
    Console.WriteLine($"Initial caller: {caller}"); 
} 
private static void Main() 
{ 
    TestIt(); 
} 

Ausgang:

Initial caller: Main 
+0

Getestet dies. Aber es gab mir "ThreadStart" –

+0

Es ist der Hauptanrufer, wenn du von einem Level aufsteigst, solltest du das Haupt finden. Aber selbst wenn Sie meine Methode ausprobieren, werden Sie einige Probleme haben. Wie ich in meiner Antwort sagte, kann der Stapel je nachdem, wo/wann du ihn nennst, geschnitten werden. –

+0

Übrigens @ René Vogt, schöne Verwendung von 4.6 Funktionen :) –

0

@kha ‚s Antwort verwenden, dies den Trick mit aus einer Schleife tun soll.

  List<StackFrame> list = new StackTrace().GetFrames().ToList(); 
      int index = list.FindIndex(p => p.GetILOffset() == StackFrame.OFFSET_UNKNOWN); 
      var methodName = list.Select(p => p.GetMethod().Name).ElementAt(index-1);