2010-06-07 24 views
4

我在字符串中保存方法體。我想動態地創建方法。但我不知道,如何設置它的身體。我看到使用CodeDom非常乏味的方式。我看到使用OpCodes發射。有沒有辦法使用字符串變量的現成代碼?是否有任何簡單的方法來創建方法並在C#中動態設置它的主體?

string method_body = "return \"Hello, world!\";"; //there is method body 
DynamicMethod dm = new System.Reflection.Emit.DynamicMethod("My_method", 
       typeof(string), new Type[] { }); //any way to create method dynamically 
//any way to set body 
string result = (string)dm.Invoke(...); //I need write result in variable 

回答

1

你需要看看這些命名空間:

System.Reflection; 
System.CodeDom.Compiler; 
Microsoft.CSharp; 

這可能讓你開始:http://www.west-wind.com/presentations/dynamicCode/DynamicCode.htm

+0

哦,謝謝!文中提供了動態編譯的準備課程,您可以參考它。 只需寫 ww腳本lo_script = new wwScripting(「CSharp」); lo_script.lSaveSourceCode = true; lo_script.AddAssembly(「mscorlib.dll」); string result =(string)lo_script.ExecuteCode(method_body,new object [] {.../* params */...}); 這是非常方便的方式。 – greatromul 2010-06-13 14:31:08

+0

這種方式可行,但只有在絕對信任輸入代碼的情況下,才應使用該方法。如果一些最終用戶(或者可能是一些可下載的內容)有能力運行代碼,那麼您應該非常小心。只是一個供參考,所以它不會讓你陷入困境。 – drharris 2010-06-15 03:07:13

1

將其保存到一個.CS文件,並在飛行中編譯和執行。

7

這聽起來像你想要什麼是「編譯器即服務」。這不在MS .NET 4.0中,但可能在更高版本中。不過,它已經在莫諾了。在此之前,可用的選項有:

  • 使用CSharpCodeProvider,但你必須在加載它作爲一種方法(和創建委託給它)通過反射
  • 使用CodeDom
  • 使用Reflection.Emit
  • 使用Expression

在4.0中,Expression API遠遠富裕比在3.5,允許在沒有最常見的結構CodeDom的痛苦。但是不要打折Reflection.Emit - 需要一點時間才能讓你的腦袋圍繞ILGenerator並使用堆棧,但它並不像人們想象的那麼糟糕。

作爲一個附註,不要使用InvokeDynamicMethod,除非你只想執行一次。更好的方法是使用CreateDelegate,然後存儲(和再利用),該委託:

var dm = new System.Reflection.Emit.DynamicMethod("My_method", 
    typeof(string), null); 
var il = dm.GetILGenerator(); 
il.Emit(OpCodes.Ldstr, "Hello, world!"); 
il.Emit(OpCodes.Ret); 
Func<string> func = (Func<string>)dm.CreateDelegate(typeof(Func<string>)); 
var s = func(); 

或者與Expression API:

var lambda =Expression.Lambda<Func<string>>(Expression.Constant("Hello, world")); 
var func = lambda.Compile(); 
var s = func(); 
相關問題