2010-08-16 19 views
5

kann Log-Methode der Klasse A erfahren, wer es anruft?Wie erhält man einen Namen der aufrufenden Methode?

class A 
{ 
    public void Log(string msg) 
    { 
     Log.Write("method_name: " + msg); 
    } 
} 

Ich möchte einen Namen der Klasse und einen Namen einer Methode wissen.

+0

So viele gute Antworten, alle Dank! – nik

Antwort

4

können Sie die StackTrace und StackFrame Klassen verwenden. Sie können entweder eine ganze Stack-Ablaufverfolgung abrufen, indem Sie den StrackTrace-Konstruktor aufrufen, oder nur einen bestimmten Stack-Frame, der den StackFrame-Konstruktor verwendet, der die Anzahl der zu überspringenden Frames annimmt.

Sie sollten sich bewusst sein, dass es aufgrund von Inlining ungenau sein kann. (e..g Methode A Inline-Methode B, die Ihre Methode aufruft - Methode A wird gemeldet, nicht B).

Beispielcode:

using System; 
using System.Diagnostics; 

class Test 
{ 
    static void ShowCaller() 
    { 
     // Use this code if you want multiple frames 
     // StackTrace trace = new StackTrace(); 
     // StackFrame frame = trace.GetFrame(1); 

     // Use this code if you're only interested in one frame 
     StackFrame frame = new StackFrame(1); 
     Console.WriteLine(frame.GetMethod()); 
    } 

    static void Intermediate() 
    { 
     ShowCaller(); 
    } 

    static void Main() 
    { 
     Intermediate(); 
    } 
} 

Lauf als optimierte Release-Build, wird diese Void Main() drucken - wenn ein Debug-Build ausgeführt wird, oder wenn Sie mehr Code in die Intermediate() Methode setzen, wird es Void Intermediate() drucken.

(Wie in den Kommentaren erwähnt, wird dies auch eine Performance-Einbußen erstellen Sie sollen es messen, um zu sehen, ob es in Ihrem speziellen Fall akzeptabel ist..)

+0

Ich habe eine Protokollierungsmethode gesehen, die absichtlich als No-Inline markiert wurde, genau aus diesem Grund. Aber, wie Sie sagten, es gibt einen erheblichen Overhead, also würde ich diese Art von Sache nicht empfehlen. –

+0

(Ich meine [MethodImpl (MethodImplOptions.NoInlining)], um genau zu sein.) –

+0

@Steven: Aber es wäre nicht die Protokollierungsmethode in diesem Fall - es wäre die Methode * Aufruf * der Protokollierungsmethode. –

2

Sie können immer step back in the call stack

+0

+1: das ist wirklich der beste Weg, es zu tun, aber achten Sie auf die Auswirkungen auf die Leistung. Ich weiß nicht genau, wie schlimm der Treffer ist, aber du solltest definitiv darüber nachdenken, ob du das in deinen Release-Builds laufen lassen willst, besonders wenn du 'Log' viel nennst. –

0

Ja, es kann - durch ein neues StackTrace Objekt erstellen und dann Verwenden Sie stackTrace.GetFrame(1).GetMethod().Name - dies ist jedoch wahrscheinlich eine teure Operation, so testen und überprüfen Sie, dass es keine übermäßige Verlangsamung Ihrer Anwendung verursacht.

+0

Log.Write ist wahrscheinlich nicht billig, also mein Kommentar re: teurness könnte verfrüht sein ... :) –

+0

Vielleicht nicht. 'Log.Write' * sollte * so billig wie möglich sein, da Sie wollen, dass es auch für die Protokollierung ohne Fehler verwendbar ist.Der übliche Weg, dies zu ermöglichen, besteht darin, es so schnell wie möglich zurückgeben zu lassen, indem der Protokolleintrag in eine Warteschlange gestellt wird, die von einem einzelnen Thread (möglicherweise mit niedrigerer Priorität) geschrieben wird. –

1

können Sie auch versuchen:

class staitc A 
    { 
     public staitc void Log(string msg) 
     { 
      Log.Write("method_name: " + msg); 
     } 
    } 


     using System.Reflection; 

class TestClass 
{ 
     // in method 

     private void TestMethod() 
    { 
      A.Log(MethodBase.GetCurrentMethod().Name +MethodBase.GetCurrentMethod().DeclaringType.FullName); 
    } 
} 
0

starten 4.5 .NET Sie Anruferinformationen durch CallerMemberNameAttribute bekommen können, die ein Teil System.Runtime.CompilerServices Namespace ist:

using System.Runtime.CompilerServices; 

class A 
{ 
    public void Log(string msg, [CallerMemberName] string memberName = "") 
    { 
     Log.Write("{0}: {1}", memberName, msg); 
    } 
} 
Verwandte Themen