C#中能否把"1+2+3"同过动态编译直接运算出来?

“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);
.......
}

控制台正确的输出了语句

温馨提示:答案为网友推荐,仅供参考
第1个回答  2014-03-26
动态编译只是用于检测程序是否存在逻辑错误(不包括编译错误)。并不能用于计算。所以不能通过动态编译来计算。只能运行(调试)才可以计算。编译错误只能通过运行程序时才会发生错误。好比1/0,这是不可能的,但是在编译时,这不会报错。当运行时就会报错。所以,楼猪想多了
第2个回答  2014-03-26
楼上正解 编译只是检测语法错误 并不能做一些运算处理 这个你运行一下有这么难吗

相关了解……

你可能感兴趣的内容

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 非常风气网