C#是一個靜態語言,也就是需要將源代碼編譯到二進制文件以后才能被執行,不像Python,Matlab等是動態執行的,也就是通過輸入語句就可以被解析器解析執行。
那C#有沒有辦法實現“字符串代碼”的執行呢?辦法是有的,.Net Framework支持在程序運行過程中將字符串編譯到程序集(dll或者exe),並可以加載。
主要用到的命名空間包含:
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.Reflection;
具體的類的使用可以參考MSDN;下面是自己的測試代碼,備忘。
1 static void Main(string[] args) 2 { 3 //類名 4 string className = "TestClass"; 5 //方法名 6 string MethodName = "TestMethod"; 7 //函數體 8 string expressionText = "return Math.Pow(x,2);"; 9 //C#代碼字符串 10 string txt = string.Format(@"using System;sealed class {0}{{public double {1} (double x){{{2}}}}}",className,MethodName,expressionText); 11 //構造一個CSharp代碼生成器 12 CSharpCodeProvider provider = new CSharpCodeProvider(); 13 //構造一個編譯器參數設置 14 CompilerParameters para = new CompilerParameters(); 15 16 /* 17 //para可以需要按照實際要求進行設置,比如添加程序集引用,如下 18 para.ReferencedAssemblies.Add("System.dll"); 19 */ 20 21 //編譯到程序集,有重載,也可以從文件加載,傳入參數為文件路徑字符串數組 22 var rst = provider.CompileAssemblyFromSource(para, new string[] { txt }); 23 24 //判斷是否有編譯錯誤 25 if(rst.Errors.Count>0) 26 { 27 foreach(CompilerError item in rst.Errors) 28 { 29 Console.WriteLine(item.Line+":"+item.ErrorText); 30 } 31 return; 32 } 33 34 //獲取程序集 35 var assemble = rst.CompiledAssembly; 36 37 //通過反射獲取類類型 38 Type t=assemble.GetType(className); 39 40 //通過類型構造實例 41 var instance=Activator.CreateInstance(t); 42 43 //通過反射獲取類型方法 44 MethodInfo method = t.GetMethod(MethodName); 45 46 //調用實例上的方法 47 var val = method.Invoke(instance, new object[] { 4 }); 48 49 Console.WriteLine(val); 50 Console.ReadKey(); 51 }