c# Obtener método de llamada sin seguimiento de pila

He notado que .NET 4.5 tiene un nuevo atributo llamado [Atributo del nombre del miembro de la llamada] que, cuando se adjunta a un parámetro de un método, proporcionará el nombre de cadena del método que llamó que método (si eso tiene sentido).

Sin embargo, desafortunadamente (porque quiero hacer algo con XNA) solo estoy apuntando a .NET 4.0.

Quiero poder hacer algo como:

void MethodA() {
   MethodB();
}

void MethodB() {
   string callingMethodName = (...?);
   Console.WriteLine(callingMethodName);
}

Dónde estaría mi salida MétodoA.

Sé que podría hacer esto a través del seguimiento de la pila, pero eso es a) poco confiable yb) muy lento... Así que me pregunto si hay alguna otra forma de obtener esa información, sin embargo, puede ser...

Esperaba alguna idea o conocimiento que alguien pudiera tener sobre el tema. Gracias por adelantado :)

preguntado el 30 de junio de 12 a las 21:06

¿Pasar el nombre del método de llamada como una cadena? -

@Oded Bueno, sí, claramente podría llamar a MethodB ("MethodA") pero el punto es que estoy tratando de hacerlo dinámicamente, de modo que si cambio MethodA a MethodC no tengo que editar esa llamada también. -

No hiciste ese punto en la pregunta. -

"¿Puedo tener características de .NET 4.5 en .NET 4.0?" Realmente no. No es fácil. El seguimiento de pila es probablemente la mejor forma dinámica de hacer esto en .NET 4.0. -

Aparentemente, puede usar el mismo truco que hicimos con ExtensionAttribute. -

2 Respuestas

Si usa Visual Studio 2012 para compilar esto, puede escribir su propio CallerMemberNameAttribute y utilícelo de la misma manera que lo haría con .NET 4.5 incluso si todavía apunta a .NET 4.0 o 3.5. El compilador aún realizará la sustitución en el momento de la compilación, incluso apuntando a una versión anterior del marco.

Simplemente agregar lo siguiente a su proyecto hará el truco:

namespace System.Runtime.CompilerServices
{
    public sealed class CallerMemberNameAttribute : Attribute { }
}

Respondido el 20 de Septiembre de 13 a las 02:09

Solo soy un programador aficionado, lo siento si esta es una pregunta estúpida, pero ¿hay alguna manera de que pueda ver la fuente de CallerMemberNameAttribute de Microsoft? Para copiarlo, quiero decir. - Xenoprimato

En general, sí, puede descompilar bibliotecas .NET usando ILSpy. wiki.sharpdevelop.net/ILSpy.ashx Sin embargo, los atributos rara vez arrojan algo interesante, ya que lo interesante es más a menudo cómo lo usa otro código. Por ejemplo, según lo que dice @ReedCopsey, el compilador realiza la transformación en el momento de la compilación, no el atributo en sí, y ni siquiera necesita el tiempo de ejecución de .NET 4.5, por lo que es probable que no vea ningún código interesante. - Tim S.

Ah, ¿entonces el compilador solo ve el nombre 'CallerMemberNameAttribute' e inserta su propia lógica? Si es así, ¿puedo crear un atributo en blanco con ese nombre y funcionará? - Xenoprimato

¡Dios mío, magia! ¿Eres un mago? Quiero leer más sobre esta magia de la sustitución del compilador, incluso cuando me dirijo a un marco anterior, ¿cuál es el término correcto para esto? - user1249190

@ user1249190 No sé si esto se publicó en ninguna parte, es solo algo que probé y que funciona;) Dado que es una característica del compilador, en general, al compilador no le importa qué marco está usando, busca el patrones para implementar características. - Reed Copsey

Puede proporcionar el nombre de la persona que llama como un parámetro para el método llamado. No es exactamente lo que está pidiendo, pero funciona sin necesidad de acceder al marco de la pila:

[MethodImpl(MethodImplOptions.NoInlining)]
void MethodA() 
{
    string methodName = System.Reflection.MethodBase.GetCurrentMethod().Name;
    MethodB(methodName);
}

void MethodB(string callingMethodName) 
{
    Console.WriteLine(callingMethodName);
}

Mediante el uso MethodBase.GetCurrentMethod(), puede asegurarse de que su implementación siga siendo segura para la refactorización: si el nombre de su método cambia, los resultados seguirán siendo correctos.

No olvide marcar su método de llamada con MethodImplOptions.NoInlining para evitar el método en línea.

Respondido el 30 de junio de 12 a las 21:06

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.