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 }