Al iniciar sesión en C #, ¿cómo puedo saber el nombre del método que llamó al método actual? Lo sé todo System.Reflection.MethodBase.GetCurrentMethod()
, pero quiero ir un paso por debajo de esto en la traza de la pila. He considerado analizar el seguimiento de la pila, pero espero encontrar una forma más explícita y limpia, algo así como Assembly.GetCallingAssembly()
métodos.
503
StackTrace
,StackFrame
yCallerMemberName
) y publicado los resultados como una esencia para que otros puedan ver aquí: gist.github.com/wilson0x4d/7b30c3913e74adf4ad99b09163a57a1fRespuestas:
Prueba esto:
un trazador de líneas:
Es de Obtener método de llamada usando Reflection [C #] .
fuente
En C # 5 puede obtener esa información utilizando la información de la persona que llama :
También puede obtener el
[CallerFilePath]
y[CallerLineNumber]
.fuente
[CallerTypeName]
se eliminó de .Net framework actual (4.6.2) y Core CLRPuede usar la información de la persona que llama y los parámetros opcionales:
Esta prueba ilustra esto:
Si bien el StackTrace funciona bastante rápido arriba y no sería un problema de rendimiento en la mayoría de los casos, la información de la persona que llama es mucho más rápida aún. En una muestra de 1000 iteraciones, lo cronometré como 40 veces más rápido.
fuente
CachingHelpers.WhoseThere("wrong name!");
==>"wrong name!"
porqueCallerMemberName
solo sustituye el valor predeterminado.this
parámetro explícito a un método de extensión. Además, Olivier es correcto, puede pasar un valor y[CallerMemberName]
no se aplica; en su lugar, funciona como una anulación donde normalmente se usaría el valor predeterminado. De hecho, si observamos la IL, podemos ver que el método resultante no es diferente de lo que normalmente se habría emitido para un[opt]
argumento,CallerMemberName
por lo tanto , la inyección de es un comportamiento CLR. Por último, los documentos: "Los atributos de Información de llamadas afectan [...] al valor predeterminado que se pasa cuando se omite el argumento "async
amigable queStackFrame
no te ayudará. Tampoco afecta ser llamado desde una lambda.Una recapitulación rápida de los 2 enfoques con la comparación de velocidad como parte importante.
http://geekswithblogs.net/BlackRabbitCoder/archive/2013/07/25/c.net-little-wonders-getting-caller-information.aspx
Determinación de la persona que llama en tiempo de compilación
Determinar la persona que llama usando la pila
Comparación de los 2 enfoques
fuente
Podemos mejorar el código del Sr. Assad (la respuesta aceptada actual) solo un poco creando instancias solo el marco que realmente necesitamos en lugar de toda la pila:
Esto podría funcionar un poco mejor, aunque con toda probabilidad todavía tiene que usar la pila completa para crear ese marco único. Además, todavía tiene las mismas advertencias que Alex Lyman señaló (el optimizador / código nativo podría corromper los resultados). Por último, es posible que desee comprobar para asegurarse de que
new StackFrame(1)
o.GetFrame(1)
no regresannull
, por improbable que esa posibilidad podría parecer.Vea esta pregunta relacionada: ¿Puede usar la reflexión para encontrar el nombre del método que se está ejecutando actualmente?
fuente
new ClassName(…)
igual a nulo?En general, puede usar la
System.Diagnostics.StackTrace
clase para obtener unSystem.Diagnostics.StackFrame
, y luego usar elGetMethod()
método para obtener unSystem.Reflection.MethodBase
objeto. Sin embargo, hay algunas advertencias sobre este enfoque:( NOTA: solo estoy ampliando la respuesta proporcionada por Firas Assad ).
fuente
A partir de .NET 4.5, puede usar los atributos de información de llamadas :
CallerFilePath
- El archivo fuente que llamó a la función;CallerLineNumber
- Línea de código que llamó a la función;CallerMemberName
- Miembro que llamó a la función.Esta instalación también está presente en ".NET Core" y ".NET Standard".
Referencias
CallerFilePathAttribute
ClaseCallerLineNumberAttribute
ClaseCallerMemberNameAttribute
Clasefuente
Tenga en cuenta que hacerlo no será confiable en el código de lanzamiento, debido a la optimización. Además, ejecutar la aplicación en modo sandbox (recurso compartido de red) no le permitirá tomar el marco de la pila.
Considere la programación orientada a aspectos (AOP), como PostSharp , que en lugar de ser llamado desde su código, modifica su código y, por lo tanto, sabe dónde está en todo momento.
fuente
Obviamente, esta es una respuesta tardía, pero tengo una mejor opción si puede usar .NET 4.5 o más:
Esto imprimirá la fecha y hora actuales, seguido de "Namespace.ClassName.MethodName" y terminando con ": text".
Salida de muestra:
Uso de la muestra:
fuente
fuente
Quizás estés buscando algo como esto:
fuente
Una clase fantástica está aquí: http://www.csharp411.com/c-get-calling-method/
fuente
Otro enfoque que he usado es agregar un parámetro al método en cuestión. Por ejemplo, en lugar de
void Foo()
usarvoid Foo(string context)
. Luego pase una cadena única que indique el contexto de la llamada.Si solo necesita el llamador / contexto para el desarrollo, puede eliminarlo
param
antes del envío.fuente
Para obtener el nombre del método y el nombre de la clase, intente esto:
fuente
será suficiente, creo.
fuente
Eche un vistazo al nombre del método de registro en .NET . Tenga cuidado de usarlo en el código de producción. StackFrame puede no ser confiable ...
fuente
También podemos usar lambda para encontrar a la persona que llama.
Supongamos que tiene un método definido por usted:
y quieres encontrar a quien llama.
1 . Cambie la firma del método para que tengamos un parámetro de tipo Acción (Func también funcionará):
2 . Los nombres lambda no se generan al azar. La regla parece ser:> <CallerMethodName> __X donde CallerMethodName se reemplaza por la función anterior y X es un índice.
3 . Cuando llamamos al Método A, el parámetro llamador debe generar el parámetro Acción / Func. Ejemplo:
4 . Dentro del Método A ahora podemos llamar a la función auxiliar definida anteriormente y encontrar el Método de Información del método del llamador.
Ejemplo:
fuente
Información adicional a la respuesta de Firas Assaad.
Lo he usado
new StackFrame(1).GetMethod().Name;
en .net core 2.1 con inyección de dependencia y recibo un método de llamada como 'Inicio'.Lo intenté
[System.Runtime.CompilerServices.CallerMemberName] string callerName = ""
y me da el método de llamada correctofuente
fuente