我想编写一个可重用的函数,我可以在任何方法中调用它来记录所有局部变量的快照。例如:
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);
}
我想获得这样的控制台输出:
step 1
Int32 a = 1
String s = something
step 2
Int32 a = 2
String s = something
String t = somethingelse
我想避免提供局部变量名称的特定列表。
我能找到的最接近的是 MethodInfo.GetCurrentMethod().GetMethodBody().LocalVariables
,但我不知道如何使用反射访问局部变量的值。
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);
}
}
反射API似乎很适合静态分析,但不适合像这样的动态分析。例如,变量 t
在第一次调用 dumpLocalVariables
时不在范围内,但它仍然出现在 的
。LocalVariables
属性中>方法主体
我怀疑我忽略了一个调试 API。 Developer Studio 如何在断点处填充“locals”选项卡?有没有办法在运行时做类似的事情?
编辑:
我可以在 ILSpy 中看到我的示例类使用 IL 代码(如 ldloc.0 和 ldloc.1)来获取第一个和第二个局部变量。
.locals init (
[0] int32 a
[1] string s
[2] string t
)
以后
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
也许我可以使用某种类似于代理的机制来让我做同样的事情?我不介意对我的可重用方法的调用是否困惑,我只想要一些我可以粘贴到任何代码块中而无需大量手动编辑的东西。
最佳答案
请参阅此相关问题:
Is there a simple way to obtain all the local variables in the current stack frame in C# (or CIL)
简短的回答是:您无法获取局部变量的值,因为它们在运行时直接分配在堆栈上,因此无法通过反射获得。做到这一点的唯一方法是通过调试器 API……这绝非易事。此外,这仅在您的自定义调试器实际附加到进程时才有效。
更好、更可行的选择可能是通过组装编织。你说你不想让方法在记录它们的值时必须知道要访问的局部变量的具体名称。我建议创建两种方法:
static void LogVariables();
和
static void LogVariables(params string[] names, params object[] values);
添加一个调用程序集编织例程的构建后任务,该例程将第一个 LogVariables 调用换成第二个,但显式地向方法提供变量名称/值。您可以编写此例程以使用 Mono Cecil 修改程序集(还有其他工具也可以执行此操作)。
关于C# 可重用函数转储局部变量的当前值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5929384/