Domanda

Vorrei scrivere una funzione riutilizzabile che posso chiamare all'interno di qualsiasi metodo per registrare un'istantanea di tutte le variabili locali. Per esempio:

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

Vorrei ottenere un output della console come questo:

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

Voglio evitare di fornire un elenco specifico di nomi delle variabili locali.

Il più vicino che ho potuto trovare era MethodInfo.GetCurrentMethod().GetMethodBody().LocalVariables, ma non so come accedere ai valori delle variabili locali usando la riflessione.

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

L'API di riflessione sembra adatta all'analisi statica, ma non per analisi dinamiche come questa. Ad esempio, la variabile t non è in portata durante la prima chiamata a dumpLocalVariables, ma appare ancora in LocalVariables Proprietà del MethodBody.

Sospetto che ci sia un'API di debug che sto trascurando. In che modo lo sviluppo di Studio popola la scheda "Locali" quando è a un punto di interruzione? C'è un modo per fare qualcosa di simile in fase di esecuzione?

MODIFICARE:

Posso vedere in Ilspy che la mia classe di esempio utilizza codici IL come ldloc.0 e ldloc.1 per raggiungere la prima e la seconda variabile locale.

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

e più tardi

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

Forse potrei usare una sorta di meccanismo simile al proxy che mi permetta di fare la stessa cosa? Non mi dispiace se la chiamata al mio metodo riutilizzabile sia disordinata, voglio solo qualcosa che posso incollare in qualsiasi blocco di codice senza molto editing a mano.

Nessuna soluzione corretta

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top