5

すべてのローカル変数のスナップショットをログに記録するために、任意のメソッド内で呼び出すことができる再利用可能な関数を作成したいと考えています。例えば:

    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引き続き表示されます。LocalVariablesMethodBody

私が見落としているデバッグ API があると思われます。Developer Studio は、ブレークポイントで「ローカル」タブをどのように設定しますか? 実行時に似たようなことをする方法はありますか?

編集:

サンプル クラスが ldloc.0 や ldloc.1 などの IL コードを使用して、1 番目と 2 番目のローカル変数を取得していることを ILSpy で確認できます。

.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

たぶん、同じことを可能にするある種のプロキシのようなメカニズムを使用できますか? 再利用可能なメソッドの呼び出しが乱雑であってもかまいません。手で編集することなく、任意のコード ブロックに貼り付けることができるものが欲しいだけです。

4

3 に答える 3

8

この関連する質問を参照してください。

C#(またはCIL)で現在のスタックフレームのすべてのローカル変数を取得する簡単な方法はありますか?

簡単に言えば、ローカル変数の値は実行時にスタックに直接割り当てられ、リフレクション経由では取得できないため、取得できません。これを行う唯一の方法は、デバッガー API を使用することです...そしてそれは簡単ではありません。さらに、これは、カスタム デバッガーが実際にプロセスに接続されている場合にのみ機能します。

より良い、より実行可能なオプションは、組み立て製織によるものかもしれません. メソッドが値をログに記録するときにアクセスするローカル変数の特定の名前を知る必要がないことをあなたは言いました。2 つのメソッドを作成することをお勧めします。

static void LogVariables();

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

最初の LogVariables 呼び出しを 2 番目の呼び出しでスワップ アウトするアセンブリ ウィービング ルーチンを呼び出すビルド後のタスクを追加しますが、メソッドに変数名/値を明示的に提供します。このルーチンを記述して、Mono Cecil を使用してアセンブリを変更できます (これを実行できるツールは他にもあります)。

http://www.mono-project.com/セシル

于 2011-05-08T18:47:07.930 に答える
2

マネージ コード用の外部デバッガを使用することで可能です。方法については、「マネージ デバッガーのサンプル」を参照してください: http://blogs.msdn.com/b/jmstall/archive/2004/09/30/236281.aspx (サンプルへのリンクと詳細情報を含む)

于 2011-05-08T18:51:01.443 に答える
0

カスタム PostSharp アスペクト (IL 変換を使用) を使用してミニダンプを作成することを検討してください。

C# で記述された共有デバッグ エンジン ライブラリ。NuGet で Microsoft.Samples.Debugging.MdbgEngine として入手できます。

PostSharp アスペクトのコードは、 PADRE ( Pluggable Automatic Debugging and Reporting Engine) リポジトリの一部として GitHub で入手できます。

于 2012-12-02T03:10:21.183 に答える