2009-03-05 9 views
46

Duplicar posibles:
How can I find the method that called the current method?Recuperando el llamado nombre de método desde dentro de un método

tengo un método en un objeto que se llama desde un número de lugares dentro del objeto. ¿Existe una manera rápida y fácil de obtener el nombre del método que llamó a este método popular?

Pseudo código de ejemplo:

public Main() 
{ 
    PopularMethod(); 
} 

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

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

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

Dentro PopularMethod() me gustaría ver el valor de Main si se llama desde Main ... Me gustaría ver "ButtonClick" si PopularMethod() fue llamado desde ButtonClick

Estaba viendo el System.Reflection.MethodBase.GetCurrentMethod(), pero eso no me da el método de llamar. Miré la clase StackTrace, pero realmente no me gustaba ejecutar un seguimiento de pila completo cada vez que se llamaba a ese método.

Respuesta

67

No creo que se puede hacer sin el seguimiento de la pila. Sin embargo, es bastante simple de hacer que:

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

Sin embargo, creo que realmente tiene que parar y preguntarse si esto es necesario.

+0

Para obtener más información, consulte: http://discuss.joelonsoftware.com/default.asp?dotnet.12.511358.10 –

+3

System.Diagnostics es el espacio de nombres de StackTrace, System.Reflection es el espacio de nombres de MethodBase. – Guvante

+0

Jason - Gracias, no estoy seguro de qué tan intensivo de recursos es el método "StackTrace", pero esto me da lo que estoy buscando. Esto es solo un bloque de código de depuración para mí, esto no entrará en producción. Gracias de nuevo por tu ayuda ! –

16

Esto es realmente muy simple.

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

Pero tenga cuidado, soy un poco escéptico si al subrayar el método tiene algún efecto. Puede hacer esto para asegurarse de que el compilador JIT no se interponga.

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

Para obtener el método de llamada:

[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

John Leidgren - Eso me dará el nombre "PopularMethod", pero quiero el nombre del método que llamó PopularMethod. –

+1

Correcto, bueno, el rastro de la pila es lo que necesita entonces. Leí mal tu pregunta. –

+0

El uso justo .GetFrame (1) en su lugar, ¿verdad? –

5

sólo tiene que pasar en un parámetro

public void PopularMethod(object sender) 
{ 

} 

IMO: Si es lo suficientemente bueno para eventos debe ser lo suficientemente bueno para esto.

+0

Sruly - Sí, eso es definitivamente una opción, estaba tratando de hacerlo sin alterar la llamada al método. Esta sería mi opción de último recurso. –

+0

A menos que exponga esto como una API pública, ¿por qué debería pasar por una molestia y usar la reflexión si puede hacerlo de esta manera? REmember KISS – Sruly

+0

Esta es la MEJOR respuesta, no use reflejo u otras cosas, identifique a la persona que llama a través de un parámetro. –

0

Creo que es necesario usar la clase StackTrace y luego StackFrame.GetMethod() en el siguiente cuadro.

Esto parece extraño para usar Reflection. Si está definiendo PopularMethod, no puede definir un parámetro o algo para pasar la información que realmente desea. (O póngalo en una clase base o algo así ...)

1

Si bien la mayoría definitivamente puede rastrear la pila y resolverlo de esa manera, le aconsejo que reconsidere su diseño. Si su método necesita saber acerca de algún tipo de "estado", yo diría simplemente crear una enumeración o algo así, y tomar eso como un parámetro para su método popular(). Algo en esa línea. En función de lo que publiques, rastrear la pila sería IMO excesivo.

4

A menudo me he encontrado con ganas de hacer esto, pero siempre he terminado refabricando el diseño de mi sistema, así que no me sale este anti-patrón "Tail wagging the dog". El resultado siempre ha sido una arquitectura más robusta.

+0

¿Es esta una respuesta? –

104

En .NET 4.5/C# 5, esto es simple:

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

El compilador añade el nombre de la persona que llama de forma automática; entonces:

void Foo() { 
    PopularMethod(); 
} 

pasará en "Foo".

+0

excelente solución !! no podemos esperar hasta convertir a 4.5 aquí (será un tiempo) pero definitivamente lo tendré en cuenta! ¡gracias! –

+1

¿Cuáles son las consecuencias de rendimiento de esta solución? – Feckmore

+3

@Feckmore ninguno en absoluto: el compilador lo agrega como un literal durante la compilación. Será significativamente más rápido que nada como mirar StackTrace, etc.básicamente se compila como PopularMethod ("CurrentMethodName") –

Cuestiones relacionadas