Pregunta

Me gustaría escribir una función reutilizable que pueda llamar dentro de cualquier método para registrar una instantánea de todas las variables locales. Por ejemplo:

    void somemethod()
    {
        int a = 1;
        string s = "something";
        dumpLocalVariables("step 1", MethodInfo.GetCurrentMethod(), this);

        a++;
        string t = s + "else";
        dumpLocalVariables("step 2", MethodInfo.GetCurrentMethod(), this);
    }

Me gustaría obtener una salida de consola como esta:

step 1
    Int32 a = 1 
    String s = something
step 2
    Int32 a = 2
    String s = something
    String t = somethingelse

Quiero evitar proporcionar una lista específica de nombres de variables locales.

Lo más cerca que pude encontrar MethodInfo.GetCurrentMethod().GetMethodBody().LocalVariables, pero no sé cómo acceder a los valores de las variables locales usando la reflexión.

void dumpLocalVariables(string context, MethodBase currentMethod, object obj)
{
    Console.WriteLine(context);
    MethodBody methodBody = currentMethod.GetMethodBody();
    foreach (LocalVariableInfo lvi in methodBody.LocalVariables)
    {
        string variableType = lvi.LocalType.Name;
        // how do I get this?
        string variableName = "variableNameHere";
        // how do I get this?    
        string variableValue = "variableValueHere";
        Console.WriteLine("   " + variableType  + " " + variableName + 
            " = " + variableValue);
    }
}

La API de reflexión parece muy adecuada para el análisis estático, pero no para un análisis dinámico como este. Por ejemplo, la variable t no está en alcance durante la primera llamada a dumpLocalVariables, pero todavía aparece en el LocalVariables propiedad del MethodBody.

Sospecho que hay una API de depuración que estoy pasando por alto. ¿Cómo puebla desarrollador Studio la pestaña "locales" cuando está en un punto de interrupción? ¿Hay alguna forma de hacer algo similar en el tiempo de ejecución?

EDITAR:

Puedo ver en ILSPY que mi clase de ejemplo usa códigos IL como LDLOC.0 y LDLOC.1 para llegar a la primera y segunda variable local.

.locals init (
    [0] int32 a
    [1] string s
    [2] string t
)

y después

IL_001b: ldloc.0  // this is a
IL_001c: ldc.i4.1
IL_001d: add
IL_001e: stloc.0
IL_001f: ldloc.1  // this is s
IL_0020: ldstr "else"
IL_0025: call string string::Concat(string, string)
IL_002a: stloc.2  // this is t

¿Tal vez podría usar algún tipo de mecanismo similar a proxy que me permita hacer lo mismo? No me importa si la llamada a mi método reutilizable es desordenado, solo quiero algo que pueda pegar en cualquier bloque de código sin mucha edición a mano.

No hay solución correcta

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top