“1+2+3"就是个字符串
事实上是可以的
但是如果你只是简单达到计算表达式的目的 根本没有必要使用动态编译 效率太低了
附关键代码段:
using System;using Microsoft.CSharp;
using System.Text;
using System.Reflection;
using System.CodeDom;
using System.CodeDom.Compiler;
static object CalcValue(string expression)
{
var codeProvider = new CSharpCodeProvider();
var parameters = new CompilerParameters();
parameters.GenerateExecutable = false;
parameters.GenerateInMemory = true;
StringBuilder sb = new StringBuilder();
sb.AppendLine("using System;");
sb.AppendLine("public class DynamicClass {");
sb.AppendLine(" public static object CalcValue() {");
sb.AppendLine(" return " + expression + ";");
sb.AppendLine(" }");
sb.AppendLine("}");
var result = codeProvider.CompileAssemblyFromSource(parameters, sb.ToString());
if (result.CompiledAssembly != null)
{
MethodInfo method = result.CompiledAssembly.GetType("DynamicClass")
.GetMethod("CalcValue", BindingFlags.Static | BindingFlags.Public);
return method.Invoke(null, null);
}
return null;
}
static void Main(string[] args)
{
object result = CalcValue("1+2+3");
Console.WriteLine("{0} ({1})", result, result.GetType());
Console.ReadKey();
}
想用更效率的办法 可以参考数据结构中栈的部分 自己编写表达式解析方法 使用逆波兰表达式进行运算
其他的可用方法可以借助javascript的eval 或借助其他动态语言嵌入(比如lua)
更多方法 可以自行搜索关键字“算术表达式求值”
追问你这代码我试过可以的,但是好像不能访问当前类的方法,貌似动态编译是编译在一个完全不相关的地方,访问不到本程序集
追答为动态编译的library添加自身程序集为引用
//....parameters.GenerateInMemory = true;
parameters.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);
StringBuilder sb = new StringBuilder();
//.....追问
我测试过了,无效果额~~~还是会报找不到
咦 你的问题是不是出在
using CSharp基础研究Studio
这句话上0 0
你添加引用的类库是"ClassLibrary1" 并不是"CSharp基础研究Studio" 这是我的推测...
试着用如下语句输出编译错误
if (result.Errors.HasErrors){
foreach (var err in result.Errors)
{
Console.WriteLine(err);
}
}追问
我改了下好了,是我写错了,但是我调用当先执行项目里的一个类的函数,函数里是Console.WriteLine,我输出的结果在当前打开的控制台里看不到的,貌似不是这个项目里的实例,我感觉这种方法等于是吧当前项目又复制了一边再执行,这个有办法解决吗?
追答不会的
当你动态编译了一个assembly并且反射调用的时候
这个assembly已经被载入到了你当前的应用程序域中
你可以使用AppDomain.Current.GetAssemblies()来查看
所以它相当于在同一个项目中执行 就像c的loadLibrary一样 你可以放心的调用
至于为什么你说的输出语句无效...我无法合理解释...我做了一个测试证明它是有效的
public class Cls1{
public object Func1()
{
Console.WriteLine("我是原程序集内的类。");
return 0;
}
}
.......
void Main(){
CalcValue("new Cls1().Func1()");
}
.......
static object CalcValue(string expression){
parameters.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);
.......
}
控制台正确的输出了语句