2014-10-20 13 views
10

Nếu tôi có một mã như thế này:Tại sao không thể lấy tên biến cục bộ bằng Reflection?

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

tôi có thể nhận được các biến địa phương khai báo trong Main sử dụng:

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

này trả về một IList<LocalVariableInfo>LocalVariableInfo chỉ có ba đặc tính: IsPinned, LocalIndexLocalType. Do đó không có tài sản Name nào tồn tại.

Những gì tôi đang tự hỏi là bạn có thể nhìn thấy tên biến trong tạo IL code:

.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 

nhưng nó không phải là khả năng để có được chúng sử dụng Reflection .là nó bởi vì các biến địa phương không có một tên và chúng chỉ được truy cập bởi các chỉ mục của chúng (nếu như vậy cách ILDASM.exe hiển thị tên?) hoặc do tính năng này không được triển khai? Hoặc nếu có thể sử dụng một cách khác thì câu hỏi sẽ là, cách?

Lưu ý: Tôi đã thấy một số câu hỏi như this và hầu hết trong số họ đang sử dụng Expressions để nhận tên biến. Nó không hoạt động nếu tôi muốn có được tất cả người dân địa phương bao gồm các biến tạm thời do trình biên dịch tạo ra.

+1

Tên có mặt sau khi xóa các tệp PDB không? – dasblinkenlight

+1

@dasblinkenlight, nhưng tôi thấy các tên tạm thời như V_0 và V_1 thay vì tên thực tế –

Trả lời

6

Bạn cần phải phân biệt giữa hình thức văn bản dựa trên con người có thể đọc được của CLI và hình thức biên soạn máy có thể đọc của CLI.

Trong văn bản CLI, các biến cục bộ thực sự có thể có tên (xem §II.15.4.1.3 của ECMA-335, như được giải thích trong câu trả lời của Damien).

Nhưng ở dạng nhị phân, biến cục bộ không có tên. Vì vậy, hãy xem §II.23.2.6, trong đó định dạng nhị phân cho chữ ký biến cục bộ của phương thức (liệt kê tất cả các biến cục bộ của phương thức) được chỉ định.Và nó không chứa bất kỳ đề cập đến tên biến:

LocalVarSig

Vì vậy, nếu một số công cụ muốn biết tên gốc của một biến địa phương, nó phải nhìn vào các thông tin gỡ lỗi chứa trong tập tin PDB . Nếu đó không phải là hiện tại, không có cách nào để tìm ra tên.

+0

Tôi cứ cố gắng tìm thông tin về cách nó thực sự được mã hóa nhưng tôi dường như không thể tìm thấy nó. –

4

Từ MSDN:

tên biến địa phương không được tiếp tục tồn tại siêu dữ liệu. Trong ngôn ngữ trung gian của Microsoft (MSIL), các biến cục bộ được truy cập bởi vị trí của chúng trong chữ ký biến cục bộ.

2

Tôi nghĩ điều này là do tên biến bạn thấy trong ILDasm đến từ tệp pdb, không phải từ bản thân hội đồng. Nếu bạn muốn nhận được chúng, bạn sẽ cần phải đọc pdb quá.

6

Tôi nghĩ bạn đang xem bản dựng Gỡ lỗi. Phần id của tuyên bố .localstùy chọn - do đó không đảm bảo rằng tên được giữ lại.

Xem MS Partition II trong đó mô tả IL Metadata, phần 15.4.1.3 để biết thêm chi tiết:

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

@PatrickHofman - cảm ơn. Vấn đề của tôi là tôi luôn luôn, tất nhiên, chỉ cần tham khảo một bản sao địa phương của các tập tin này nhưng sau đó đấu tranh với việc cung cấp một liên kết. –

Các vấn đề liên quan