2012-03-27 69 views
3

不久前我開始學習使用System.Reflection.Emit命名空間。現在我正在努力把這種代碼中使用的ILGenerator的:如何翻譯新的對象創建?

MyClass c = new MyClass("MyClass"); 
c.Do(":D"); 

對於這段代碼我有三個問題:如何創建對象?如何調用構造器以及如何調用類的方法?請幫忙。

+4

最好的方式來學習什麼是C#做幕後是看在IL,它生成的代碼。我假設你知道如何看待調試器中的反彙編,對吧? – dasblinkenlight 2012-03-27 16:14:03

+0

好的。謝謝你們。 – user35443 2012-03-27 18:12:21

回答

3

下面是一個完整的示例,顯示必要的IL代碼。

可以在LINQPad測試:

void Main() 
{ 
    // Manual test first 
    MyClass c = new MyClass("MyClass"); 
    c.Do(":D"); 

    var method = new DynamicMethod("dummy", null, Type.EmptyTypes); 
    var il = method.GetILGenerator(); 

    // <stack> = new MyClass("MyClass"); 
    il.Emit(OpCodes.Ldstr, "MyClass"); 
    il.Emit(OpCodes.Newobj, typeof(MyClass).GetConstructor(new[] { typeof(string) })); 

    // <stack>.Do(":D"); 
    il.Emit(OpCodes.Ldstr, ":D"); 
    il.Emit(OpCodes.Call, typeof(MyClass).GetMethod("Do", new[] { typeof(string) })); 

    // return; 
    il.Emit(OpCodes.Ret); 

    var action = (Action)method.CreateDelegate(typeof(Action)); 
    action(); 
} 

public class MyClass 
{ 
    public MyClass(string text) 
    { 
     Console.WriteLine("MyClass(" + text + ")"); 
    } 

    public void Do(string text) 
    { 
     Console.WriteLine("Do(" + text + ")"); 
    } 
} 

輸出:

MyClass(MyClass) 
Do(:D) 
MyClass(MyClass) 
Do(:D) 

順便說一句,你可以使用LINQPad獲得IL代碼擱置了具體的例子。讓我切出的上述示例中的IL-部分,像這樣(I除去類爲好,這是相同的類):

void Main() 
{ 
    MyClass c = new MyClass("MyClass"); 
    c.Do(":D"); 
} 

通過執行該代碼,然後使用輸出的IL標籤,你可以看到生成的代碼:

LINQPad IL Output

的兩條指令stloc.0ldloc.0是在代碼中的變量。

的IL我發射的第一類似於這段代碼:

new MyClass("MyClass").Do(":D"); 

即沒有變量,在棧上只是臨時存儲,而事實上:

LINQPad IL output #2