2010-08-16 10 views
5

¿Puede el método de registro de clase A saber quién lo llama?¿Cómo obtener el nombre del método de llamada?

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

Quiero saber el nombre de la clase y el nombre del método.

+0

Tantas buenas respuestas, gracias todos! – nik

Respuesta

4

Puede utilizar los StackTrace y StackFrame clases. Puede obtener un seguimiento de pila completo llamando al constructor StrackTrace, o solo un marco de pila particular utilizando el constructor StackFrame, que toma el número de fotogramas para omitir.

Debe tener en cuenta que puede ser impreciso debido a la alineación. (e.g método A enlista el método B que llama a su método - se informará el método A, no B).

Código de ejemplo:

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(); 
    } 
} 

ejecuta como una versión de lanzamiento optimizado, esto imprimirá Void Main() - cuando se ejecuta una versión de depuración, o si se pone más código en el método Intermediate(), se imprimirá Void Intermediate().

(Como se mencionó en los comentarios, esto también crear un impacto en el rendimiento Se debe medir para ver si es aceptable en su caso particular..)

+0

He visto un método de registro marcado intencionalmente como no en línea, precisamente por este motivo. Pero, como dijiste, hay una sobrecarga significativa, así que no recomendaría ese tipo de cosas. –

+0

(Me refiero a [MethodImpl (MethodImplOptions.NoInlining)], para ser específico.) –

+0

@Steven: Pero no sería el método de registro en este caso, sería el método * llamando * al método de registro. –

2

siempre se puede step back in the call stack

+0

+1: esta es realmente la mejor manera de hacerlo, pero ten cuidado con las implicaciones de rendimiento. No sé exactamente qué tan malo es el éxito, pero definitivamente debes considerar si quieres que esto se ejecute en tus compilaciones de lanzamiento, especialmente si llamas 'Log' mucho. –

0

Sí, se puede - mediante la creación de un nuevo StackTrace objeto y luego use stackTrace.GetFrame(1).GetMethod().Name - sin embargo, es probable que sea una operación costosa, por lo tanto, verifique y compruebe que no cause una desaceleración excesiva de su aplicación.

+0

Log.Write probablemente no es barato, así que mi comentario es: el costo puede ser prematuro ... :) –

+0

Quizás no. 'Log.Write' * debería * ser lo más barato posible, ya que también se puede usar para el registro sin errores.La forma habitual de hacerlo posible es hacer que regrese tan rápido como sea posible, colocando la entrada de registro en una cola escrita por un solo hilo (potencialmente con menor prioridad). –

1

también puede probar:

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

partir .NET 4.5 se puede obtener información de la llamada a través CallerMemberNameAttribute, que es una parte del espacio de nombres System.Runtime.CompilerServices:

using System.Runtime.CompilerServices; 

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