2014-10-20 4 views
10

Wenn ich einen Code wie folgt:Warum ist es nicht möglich, lokale Variablennamen mit Reflection zu erhalten?

public class Program 
{ 
    public static void Main() 
    { 
     string bar = ""; 
     int foo = 24; 
    } 
} 

Ich kann die lokalen Variablen in Main erklärt bekommen mit:

var flag = BindingFlags.Static | BindingFlags.Public; 
var fields = typeof(Program).GetMethod("Main", flags).GetMethodBody().LocalVariables; 

Dies gibt eine IList<LocalVariableInfo> und die LocalVariableInfo hat nur drei Eigenschaften: IsPinned, LocalIndex und LocalType. So gibt es keine Name Eigenschaft existiert.

Was ich frage mich, ist, dass Sie die Variablennamen in der generierten IL code sehen:

.method public hidebysig static void Main() cil managed 
{ 
    .entrypoint 
    // Code size  11 (0xb) 
    .maxstack 1 
    .locals init ([0] string bar, 
      [1] int32 foo) 
    IL_0000: nop 
    IL_0001: ldstr  "" 
    IL_0006: stloc.0 
    IL_0007: ldc.i4.s 24 
    IL_0009: stloc.1 
    IL_000a: ret 
} // end of method Program::Main 

aber es ist nicht möglich, sie Reflection .ist es zu bekommen verwenden, da lokale Variablen nicht eine haben Name und sie werden nur von ihren Indizes zugegriffen (wenn ja, wie die ILDASM.exe zeigt die Namen?), oder weil eine solche Funktion nicht implementiert ist? Oder wenn es möglich ist, einen anderen Weg zu verwenden, dann wäre die Frage wie?

Hinweis: Ich habe einige Fragen wie this gesehen und die meisten von ihnen verwenden Expressions, um Variablennamen zu erhalten. Es funktioniert nicht, wenn ich alle lokalen einschließlich temporärer Variablen, die vom Compiler generiert wurden, erhalten möchte.

+1

Sind Namen nach dem Entfernen von PDB-Dateien vorhanden? – dasblinkenlight

+1

@dasblinkenlight sie sind, aber ich sehe temporäre Namen wie V_0 und V_1 anstelle der tatsächlichen Namen –

Antwort

6

Sie haben zwischen den Menschen lesbaren textbasierte Form von CLI und der maschinenlesbaren kompilierter Form zu unterscheiden von CLI.

In Text-CLI können lokale Variablen tatsächlich Namen haben (siehe §II.15.4.1.3 von ECMA-335, wie in Damiens Antwort erklärt).

Aber in der binären Form haben lokale Variablen keine Namen. Sehen Sie dazu in §II.23.2.6 nach, wo das Binärformat für die lokale Variablensignatur einer Methode (Liste aller lokalen Variablen) angegeben ist.Und es enthält keine Erwähnung von Variablennamen:

LocalVarSig

Also, wenn irgendein Tool den ursprünglichen Namen einer lokalen Variablen wissen will, hat es in die Debug-Informationen in der PDB-Datei enthalten sind, zu sehen . Wenn das nicht vorhanden ist, gibt es keine Möglichkeit, den Namen herauszufinden.

+0

Ich habe versucht, Informationen darüber zu finden, wie es tatsächlich codiert wurde, aber ich konnte es einfach nicht finden. –

4

Von MSDN:

Lokale Variablennamen werden nicht in den Metadaten beibehalten. In Microsoft-Zwischensprache (MSIL) wird auf lokale Variablen durch ihre Position in der lokalen Variablensignatur zugegriffen.

2

Ich denke, das liegt daran, dass der Variablenname, den Sie in ILDasm sehen, von der PDB-Datei kommt, nicht von der Assembly selbst. Wenn Sie sie bekommen wollen, müssen Sie auch die pdb lesen.

6

Ich denke, Sie betrachten eine Debug-Build. Der id Teil der .locals Erklärung ist optional - so gibt es keine Garantie, dass die Namen beibehalten werden.

Siehe MS Partition II, die die IL-Metadaten, Abschnitt 15.4.1.3 für weitere Details beschreiben:

MethodBodyItem ::= … 
    .locals [ init ] ‘(’ LocalsSignature ‘)’ 
LocalsSignature ::= Local [ ‘,’ Local ]* 
Local ::= Type [ Id ] 
+1

@PatrickHofman - danke. Mein Problem ist, dass ich mich immer nur auf eine lokale Kopie dieser Dateien beziehe, aber dann mit der Bereitstellung eines Links kämpfe. –

Verwandte Themen