C # многоразовая функция для сброса текущего значения локальных переменных - PullRequest
5 голосов
/ 08 мая 2011

Я хотел бы написать функцию многократного использования, которую я могу вызвать в любом методе, чтобы записать снимок всех локальных переменных.Например:

    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 заполняет вкладку «locals» в точке останова?Есть ли способ сделать что-то подобное во время выполнения?

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

Может быть, я мог бы использовать какой-то прокси-подобный механизм, который позволяет мне делать то же самое?Я не возражаю, если вызов моего метода многократного использования является грязным, я просто хочу что-то, что я могу вставить в любой блок кода без большого количества ручного редактирования.

Ответы [ 3 ]

8 голосов
/ 08 мая 2011

См. Этот связанный вопрос:

Есть ли простой способ получить все локальные переменные в текущем стековом кадре в C # (или CIL)

ShortОтвет таков: вы не можете получить значения локальных переменных, потому что они размещаются непосредственно в стеке во время выполнения и, следовательно, недоступны для отражения.Единственный способ сделать это - через API отладчика ... и это далеко не тривиально.Кроме того, это будет работать только в том случае, если ваш пользовательский отладчик действительно подключен к процессу.

Лучшим, более выполнимым вариантом может быть переплетение сборок.Вы сказали, что не хотите, чтобы метод знал конкретные имена локальных переменных для доступа при регистрации их значений.Я бы предложил создать два метода:

static void LogVariables();

и

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

Добавить задачу посткомпоновки, которая вызывает подпрограмму сборки, которая заменяет первый вызов LogVariables на второй, но явнопредоставление имен / значений переменных в метод.Вы можете написать эту процедуру для изменения сборки, используя Mono Cecil (есть и другие инструменты, которые могут это сделать).

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

2 голосов
/ 08 мая 2011

Это возможно при использовании внешнего отладчика для управляемого кода.См. «Пример управляемого отладчика», чтобы узнать, как это сделать: http://blogs.msdn.com/b/jmstall/archive/2004/09/30/236281.aspx (включает ссылку на образец и дополнительную информацию)

0 голосов
/ 02 декабря 2012

Рассмотрим запись мини-дампов с использованием пользовательского аспекта PostSharp (с преобразованием IL ).

Общая библиотека механизма отладки, написанная на C #.доступно в NuGet как Microsoft.Samples.Debugging.MdbgEngine.

Код аспекта PostSharp доступен на GitHub как часть репозитория PADRE (Pluggable Automatic Debugging and Reporting Engine)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...