Я хотел бы написать функцию многократного использования, которую я могу вызвать в любом методе, чтобы регистрировать моментальный снимок всех локальных переменных. Например:
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
объекта MethodBody
.
Я подозреваю, что есть API отладки, который я упускал из виду. Как Developer Studio заполняет вкладку «местные», когда находится в точке останова? Есть ли способ сделать что-то подобное во время выполнения?
EDIT:
Я вижу в 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
Может быть, я мог бы использовать какой-нибудь механизм, похожий на прокси, который позволяет мне делать то же самое? Я не против, если вызов моего многоразового метода будет беспорядочным, Мне просто нужно что-то, что можно вставить в любой блок кода без особого редактирования вручную.