Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
918 views
in Technique[技术] by (71.8m points)

debugging - C# reusable function to dump current value of local variables

I would like to write a reusable function I can call within any method to log a snapshot of all the local variables. For example:

    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);
    }

I would like to get a console output like this:

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

I want to avoid providing a specific list of local variable names.

The closest I could find was MethodInfo.GetCurrentMethod().GetMethodBody().LocalVariables, but I do not know how to access the values of the local variables using reflection.

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);
    }
}

The reflection API seems well suited for static analysis, but not for dynamic analysis like this. For instance, the variable t is not in scope during the first call to dumpLocalVariables, but it still appears in the LocalVariables property of the MethodBody.

I suspect there is a debugging API that I am overlooking. How does Developer Studio populate the "locals" tab when at a breakpoint? Is there a way to do something similar at runtime?

EDIT:

I can see in ILSpy that my example class uses IL codes like ldloc.0 and ldloc.1 to get to the first and second local variable.

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

and later

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

Maybe I could use some sort of proxy-like mechanism that lets me do the same thing? I don't mind if the call to my reusable method is messy, I just want something I can paste into any code block without a lot of hand-editing.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

See this related question:

Is there a simple way to obtain all the local variables in the current stack frame in C# (or CIL)

The short answer is: you can't get the values of the local variables because they're allocated directly on the stack at runtime, and thus are not available via reflection. The only way to do this is via the debugger API...and it's far from trivial. Further, this would only work if your custom debugger is actually attached to the process.

A better, more feasible option might be via assembly weaving. You said you don't want to have the method have to know the specific names of local variables to access when logging their values. I would suggest creating two methods:

static void LogVariables();

and

static void LogVariables(params string[] names, params object[] values);

Add a post build task that calls an assembly weaving routine that swaps out the first LogVariables call with the second, but explicitly providing the variable names/values to the method. You can write this routine to modify the assembly using Mono Cecil (there are other tools too that can do this).

http://www.mono-project.com/Cecil


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...