¿Cómo puedo encontrar el método que llamó el método actual?

Al iniciar sesión en C#, ¿cómo puedo aprender el nombre del método que llamó el método actual? Sé todo sobre System.Reflection.MethodBase.GetCurrentMethod(), pero quiero ir un paso debajo de esto en el rastro de la pila. He considerado analizar el rastro de la pila, pero espero encontrar un limpiador de manera más explícita, algo como Assembly.GetCallingAssembly() pero para métodos.

Pregunta hecha hace 15 años, 4 meses, 23 días - Por codechampionx


11 Respuestas:

  • Prueba esto:

    using System.Diagnostics;
    // Get call stack
    StackTrace stackTrace = new StackTrace(); 
    // Get calling method name
    Console.WriteLine(stackTrace.GetFrame(1).GetMethod().Name);
    

    Una línea:

    (new System.Diagnostics.StackTrace()).GetFrame(1).GetMethod().Name
    

    Respondida el Oct 05, 2008 a las 13:34 - por techtrailblazer

    Votos positivos: 0 | Votos negativos: 0

  • En C# 5, puede obtener esa información usando caller info:

    //using System.Runtime.CompilerServices;
    public void SendError(string Message, [CallerMemberName] string callerName = "") 
    { 
        Console.WriteLine(callerName + "called me."); 
    } 
    

    También puede conseguir el [CallerFilePath] y [CallerLineNumber].

    Respondida el Oct 05, 2008 a las 13:42 - por bytebison

    Votos positivos: 0 | Votos negativos: 0

  • Puede utilizar la información de llamada y parámetros opcionales:

    public static string WhoseThere([CallerMemberName] string memberName = "")
    {
           return memberName;
    }
    

    Esta prueba ilustra esto:

    [Test]
    public void Should_get_name_of_calling_method()
    {
        var methodName = CachingHelpers.WhoseThere();
        Assert.That(methodName, Is.EqualTo("Should_get_name_of_calling_method"));
    }
    

    Mientras que el StackTrace funciona bastante rápido por encima y no sería un problema de rendimiento en la mayoría de los casos la información de llamada es mucho más rápido todavía. En una muestra de 1000 iteraciones, lo reloj como 40 veces más rápido.

    Respondida el Oct 05, 2008 a las 13:52 - por pythonpirate

    Votos positivos: 0 | Votos negativos: 0

  • Una rápida recuperación de los 2 enfoques con la comparación de velocidad es la parte importante.

    http://geekswithblogs.net/BlackRabbitCoder/archive/2013/07/25/c.net-little-wonders-getting-caller-information.aspx

    Determinación de la llamada a tiempo de compilación

    static void Log(object message, 
    [CallerMemberName] string memberName = "",
    [CallerFilePath] string fileName = "",
    [CallerLineNumber] int lineNumber = 0)
    {
        // we'll just use a simple Console write for now    
        Console.WriteLine("{0}({1}):{2} - {3}", fileName, lineNumber, memberName, message);
    }
    

    Determinar el callador usando la pila

    static void Log(object message)
    {
        // frame 1, true for source info
        StackFrame frame = new StackFrame(1, true);
        var method = frame.GetMethod();
        var fileName = frame.GetFileName();
        var lineNumber = frame.GetFileLineNumber();
    
        // we'll just use a simple Console write for now    
        Console.WriteLine("{0}({1}):{2} - {3}", fileName, lineNumber, method.Name, message);
    }
    

    Comparación de los 2 enfoques

    Time for 1,000,000 iterations with Attributes: 196 ms
    Time for 1,000,000 iterations with StackTrace: 5096 ms
    

    Así que verás, usar los atributos es mucho, mucho más rápido! Casi 25x más rápido de hecho.

    Respondida el Oct 05, 2008 a las 14:01 - por apiartisan

    Votos positivos: 0 | Votos negativos: 0

  • Podemos mejorar el código del Sr. Assad (la respuesta aceptada actual) sólo un poco al instantánear sólo el marco que realmente necesitamos en lugar de toda la pila:

    new StackFrame(1).GetMethod().Name;
    

    Esto podría funcionar un poco mejor, aunque en toda probabilidad todavía tiene que utilizar la pila completa para crear ese marco único. Además, todavía tiene las mismas cavernas que Alex Lyman señaló (optimizer/native code podría dañar los resultados). Por último, es posible que desee comprobar que new StackFrame(1) o .GetFrame(1) No regreses null, tan poco probable como esa posibilidad podría parecer.

    Véase esta pregunta relacionada: ¿Puede utilizar la reflexión para encontrar el nombre del método de ejecución actual?

    Respondida el Oct 05, 2008 a las 14:11 - por devdoodle

    Votos positivos: 0 | Votos negativos: 0

  • En general, puede utilizar el System.Diagnostics.StackTrace clase para conseguir un System.Diagnostics.StackFrame, y luego utilizar el GetMethod() método para obtener un System.Reflection.MethodBase objeto. Sin embargo, hay algunas cavernas a este enfoque:

    1. Representa a la Hora de correr apilar -- optimizaciones podrían inlinear un método, y usted va a no ver ese método en el rastro de la pila.
    2. Lo hará. no mostrar cualquier marco nativo, así que si hay una posibilidad de que su método sea llamado por un método nativo, esto lo hará no el trabajo, y no hay forma disponible actualmente para hacerlo.

    ()NOTA: Sólo estoy en expansión la respuesta proporcionado por Firas Assad)

    Respondida el Oct 05, 2008 a las 14:19 - por bytebison

    Votos positivos: 0 | Votos negativos: 0

  • En .NET 4.5 se puede utilizar Información de llamadas Atributos:

    • 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.

      public void WriteLine(
          [CallerFilePath] string callerFilePath = "", 
          [CallerLineNumber] long callerLineNumber = 0,
          [CallerMemberName] string callerMember= "")
      {
          Debug.WriteLine(
              "Caller File Path: {0}, Caller Line Number: {1}, Caller Member: {2}", 
              callerFilePath,
              callerLineNumber,
              callerMember);
      }
      

    Esta instalación también está presente en ".NET Core" y ".NET Standard".

    Referencias

    1. Microsoft - Información de llamadas (C#)
    2. Microsoft - CallerFilePathAttribute Clase
    3. Microsoft - CallerLineNumberAttribute Clase
    4. Microsoft - CallerMemberNameAttribute Clase

    Respondida el Oct 05, 2008 a las 14:24 - por debugduke

    Votos positivos: 0 | Votos negativos: 0

  • Obviamente esta es una respuesta tardía, pero tengo una mejor opción si puedes usar .NET 4.5 o más reciente:

    internal static void WriteInformation(string text, [CallerMemberName]string method = "")
    {
        Console.WriteLine(DateTime.Now.ToString() + " => " + typeof(T).FullName + "." + method + ": " + text);
    }
    

    Esto imprimirá la fecha y el tiempo actuales, seguido de "Namespace.ClassName.MethodName" y terminando con ": texto".
    Salida de la muestra:

    6/17/2016 12:41:49 PM => WpfApplication.MainWindow..ctor: MainWindow initialized
    

    Uso de la muestra:

    Logger.WriteInformation("MainWindow initialized");
    

    Respondida el Oct 05, 2008 a las 14:33 - por cyberscribe

    Votos positivos: 0 | Votos negativos: 0

  • Tenga en cuenta que hacerlo no será fiable en el código de liberación, debido a la optimización. Además, ejecutar la aplicación en modo sandbox (parte de red) no le permitirá agarrar el marco de la pila en absoluto.

    Considerar programación orientada hacia los aspectos (AOP), como PostSharp, que en lugar de ser llamado de su código, modifica su código, y por lo tanto sabe dónde está en todo momento.

    Respondida el Oct 05, 2008 a las 14:43 - por rubyrogue

    Votos positivos: 0 | Votos negativos: 0

  • En C

    , para obtener el nombre del método que llamó al método actual, puedes utilizar la clase System.Diagnostics.StackTrace. Aquí te muestro un ejemplo de cómo puedes hacerlo:

    csharp
    using System;
    using System.Diagnostics;
    
    class Program
    {
        static void Main()
        {
            MetodoA();
        }
    
        static void MetodoA()
        {
            string nombreMetodoLlamador = new StackTrace().GetFrame(1).GetMethod().Name;
            Console.WriteLine($"El nombre del método que llamó a MetodoA es: {nombreMetodoLlamador}");
        }
    }
    

    En el ejemplo anterior, MetodoA() obtiene el nombre del método que lo llamó utilizando StackTrace().GetFrame(1).GetMethod().Name. Esto obtendrá el nombre del método que se encuentra en la posición inmediatamente superior en la pila de llamadas. Puedes modificar este índice según la posición requerida en la pila de llamadas.

    Es importante señalar que el uso de la clase StackTrace puede tener un impacto en el rendimiento de la aplicación, por lo que se recomienda utilizarlo solo cuando sea necesario, como en casos de depuración o traz

    Respondida el Oct 06, 2008 a las 13:33 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Aquí tienes algunas formas de encontrar el método que llamó al método actual en C

    :

    Usando StackTrace:

    csharp
    StackFrame frame = new StackFrame(1);
    MethodBase callingMethod = frame.GetMethod();
    

    Usando System.Reflection.Emit.AssemblyBuilder.DefineDynamicMethod:

    csharp
    var methodName = new StackTrace().GetFrame(1).GetMethod().Name;
    

    Usando Reflection.Emit para crear un método dinámico:

    csharp
    using System.Reflection.Emit;
    using System.Runtime.CompilerServices;
    
    public static class CallerInfo
    {
        public static string GetCallingMethodName()
        {
            DynamicMethod method = new DynamicMethod(
                "GetCallingMethodName",
                typeof(string),
                new Type[0],
                ModuleBuilder.GetCurrentModule()
            );
            ILGenerator il = method.GetILGenerator();
            il.Emit(OpCodes.Ldstr, GetCallingMethodName().ToString());
            il.Emit(OpCodes.Ret);
            return (string)method.Invoke(null, null);
        }
    }
    

    ADVERTENCIA: Ten en cuenta que estos métodos pueden no funcionar correctamente en todos los casos, especialmente si el código ha sido compilado con optimizaciones o si se utilizan técnicas de reflexión avanzada.

    Respondida el Oct 06, 2008 a las 13:45 - por Gemini

    Votos positivos: 0 | Votos negativos: 0