2011-01-21 35 views
28

Có thể xem mã IL được tạo khi bạn gọi Biên dịch() trên cây Biểu thức không? Hãy xem xét ví dụ rất đơn giản này:Xem mã IL được tạo từ biểu thức được biên dịch

class Program 
{ 
    public int Value { get; set; } 

    static void Main(string[] args) 
    { 
     var param = Expression.Parameter(typeof(Program)); 
     var con = Expression.Constant(5); 
     var prop = Expression.Property(param, typeof(Program).GetProperty("Value")); 
     var assign = Expression.Assign(prop, con); 
     Action<Program> lambda = Expression.Lambda<Action<Program>>(assign, param).Compile(); 

     Program p = new Program(); 
     lambda(p); 



     //p.Value = 5; 
    } 
} 

Bây giờ, cây biểu thức làm dòng cuối cùng của Main nói. Biên dịch ứng dụng, sau đó mở nó trong Reflector. Bạn có thể thấy mã IL của p.Value = 5; thực hiện nhiệm vụ. Nhưng cây biểu hiện được tạo và biên dịch trong thời gian chạy. Có thể xem mã IL kết quả từ biên dịch không?

+0

Bạn chỉ muốn * tương đương * IL cho những gì bạn đang * làm * (ví dụ: thiết lập một tài sản)? Hay có điều gì đó về đầu ra 'Expression' mà bạn đặc biệt quan tâm? –

+0

Không có gì cụ thể. Tôi thích nhìn vào mã IL theo thời gian. Nhưng với các biểu thức bạn có thể tạo ra một phương thức không nhận được bất kỳ IL nào trong assembly được biên dịch. IL sử dụng để * tạo * cây biểu thức đó, nhưng không phải là kết quả của việc biên dịch của cây biểu thức. Điều đó có ý nghĩa? Đây chỉ đơn giản là một sự tò mò và không phục vụ bất kỳ mục đích thiết thực nào mà tôi có thể nhìn thấy. – Amy

+1

Bạn đã thử với công cụ ** LinqPad ** tuyệt vời chưa? http://www.linqpad.net/ Với nó, bạn có thể hiển thị mã được tạo ra như MSIL và thử nghiệm nhanh chóng gần như bất cứ điều gì ... – AFract

Trả lời

28

Có! Sử dụng công cụ này:

http://blogs.msdn.com/b/haibo_luo/archive/2006/11/16/take-two-il-visualizer.aspx

Đây là vô cùng hữu ích khi tôi đã thực hiện và gỡ lỗi Compile, như tôi chắc chắn rằng bạn có thể tưởng tượng.

+3

Eric, nếu bạn có thời gian, bạn có thể xác định điều này thành một câu trả lời đáng kể hơn? Chỉ liên kết các câu trả lời không được khuyến khích trên Stack Overflow. – casperOne

+0

Quá xấu nó không phải là compilable, là có một phiên bản nhị phân có sẵn? –

+2

@casperOne: Tôi khuyến khích bạn làm như vậy. Tôi không có gì để thêm vào. –

21

Tạo một DynamicAssembly, sau đó là DynamicModule, DynamicType và DynamicMethod. Làm cho phương thức đó công khai và tĩnh và chuyển nó tới phương thức CompileTo() trên lambda. Khi bạn thực hiện việc lắp ráp cờ nó như là Lưu. Sau đó gọi phương thức Save() và truyền một đường dẫn. Nó sẽ được ghi vào đĩa. Pop nó mở trong phản xạ.

Cái gì như:

var da = AppDomain.CurrentDomain.DefineDynamicAssembly(
    new AssemblyName("dyn"), // call it whatever you want 
    AssemblyBuilderAccess.Save); 

var dm = da.DefineDynamicModule("dyn_mod", "dyn.dll"); 
var dt = dm.DefineType("dyn_type"); 
var method = dt.DefineMethod(
    "Foo", 
    MethodAttributes.Public | MethodAttributes.Static); 

lambda.CompileToMethod(method); 
dt.CreateType(); 

da.Save("dyn.dll"); 
+0

trong trường hợp bất kỳ ai quan tâm đến việc xóa 'MethodAttributes.Static' khỏi phương thức' DefineMethod', có một số nghiên cứu tôi nhận được http://stackoverflow.com/a/3993023/903505 trong kết luận, 'CompileToMethod' chỉ hoạt động với tĩnh phương pháp – Ariex

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