今天在论坛里面逛发现一个问题比较典型,我们在使用js的时候可以直接使用Eval得到某一个表达式的值,在C#里面可以吗?答案是肯定的,在.NET提供的丰富的类库里面这是可以实现的,但是没有js那么简单下面我将使用一个简单的例子来说明利用编译器和反射得到一个字符串表达式的值。我们建立一个Windows窗体里面有如下的方法:
引用一下命名空间:
using System;
using System.Text;
using System.CodeDom.Compiler;
using System.Reflection;
using System.IO;
using Microsoft.CSharp;
命名空间的具体意义就不说了,下面看看代码,为了可以让我们的工程可以重复使用我们新建一个类库工程名叫:CoustomEval其中有一个类是用来计算某一断字符串的值。详细代码如下所示:
namespace CoustomEval{
///
/// Summary description for Class1.
///
public class MyEval{
public MyEval(){
//
// TODO: Add constructor logic here
//
}
public object Eval(string cCharpCode){
CSharpCodeProvider csharpCodeProvider = new CSharpCodeProvider();
ICodeCompiler compiler = csharpCodeProvider.CreateCompiler();
CompilerParameters cp = new CompilerParameters();
cp.ReferencedAssemblies.Add("system.dll");
cp.CompilerOptions = "/t:library";
cp.GenerateInMemory = true;
StringBuilder myCode = new StringBuilder();
myCode.Append("using System;");
myCode.Append("namespace CoustomEval{");
myCode.Append("class myLib {private "+cCharpCode+" public int myMethod(){return i;}}");
myCode.Append("}");
CompilerResults cr = compiler.CompileAssemblyFromSource(cp,myCode.ToString());
Assembly assembly = cr.CompiledAssembly;
object tmp = assembly.CreateInstance("CoustomEval.myLib");
Type type = tmp.GetType();
MethodInfo mi = type.GetMethod("myMethod");
object result = mi.Invoke(tmp,null);
return result;
}
}
}
上面的类库只具有一般代表性不具备一般使用性,重要的是提供一种方法来实现它,所以我在里面使用了硬编码的方式,如果你喜欢可以使用其他的方式,包括读文件,读数据库取得代码段等等。然后我们在建立一个测试工程,该工程里面有一个测试窗体,该窗体上有一个按钮和两个文本框,其中一个文文本框用来输入要计算的值,另一个显示计算的结果,详细代码如下:
private void button1_Click(object sender, System.EventArgs e) {
MyEval eval = new MyEval();
object result = eval.Eval(this.textBox1.Text);
this.textBox2.Text = result.ToString();
}
在这个工程中需要引用上面的工程,这样我们就可以使用MyEval类来实现计算TextBox1里面的值了,最后可以将值显示在TextBox2里面,代码运行的结果我在这里就不帖了。只给出我的测试结果,由于该问题源于论坛所以我就是用论坛中原来的测试要求。
测试结果:在TextBox中输入int i = 10;点击Button1以后将会在TextBox2中显示出10。
引用一下命名空间:
using System;
using System.Text;
using System.CodeDom.Compiler;
using System.Reflection;
using System.IO;
using Microsoft.CSharp;
命名空间的具体意义就不说了,下面看看代码,为了可以让我们的工程可以重复使用我们新建一个类库工程名叫:CoustomEval其中有一个类是用来计算某一断字符串的值。详细代码如下所示:
namespace CoustomEval{
///
/// Summary description for Class1.
///
public class MyEval{
public MyEval(){
//
// TODO: Add constructor logic here
//
}
public object Eval(string cCharpCode){
CSharpCodeProvider csharpCodeProvider = new CSharpCodeProvider();
ICodeCompiler compiler = csharpCodeProvider.CreateCompiler();
CompilerParameters cp = new CompilerParameters();
cp.ReferencedAssemblies.Add("system.dll");
cp.CompilerOptions = "/t:library";
cp.GenerateInMemory = true;
StringBuilder myCode = new StringBuilder();
myCode.Append("using System;");
myCode.Append("namespace CoustomEval{");
myCode.Append("class myLib {private "+cCharpCode+" public int myMethod(){return i;}}");
myCode.Append("}");
CompilerResults cr = compiler.CompileAssemblyFromSource(cp,myCode.ToString());
Assembly assembly = cr.CompiledAssembly;
object tmp = assembly.CreateInstance("CoustomEval.myLib");
Type type = tmp.GetType();
MethodInfo mi = type.GetMethod("myMethod");
object result = mi.Invoke(tmp,null);
return result;
}
}
}
上面的类库只具有一般代表性不具备一般使用性,重要的是提供一种方法来实现它,所以我在里面使用了硬编码的方式,如果你喜欢可以使用其他的方式,包括读文件,读数据库取得代码段等等。然后我们在建立一个测试工程,该工程里面有一个测试窗体,该窗体上有一个按钮和两个文本框,其中一个文文本框用来输入要计算的值,另一个显示计算的结果,详细代码如下:
private void button1_Click(object sender, System.EventArgs e) {
MyEval eval = new MyEval();
object result = eval.Eval(this.textBox1.Text);
this.textBox2.Text = result.ToString();
}
在这个工程中需要引用上面的工程,这样我们就可以使用MyEval类来实现计算TextBox1里面的值了,最后可以将值显示在TextBox2里面,代码运行的结果我在这里就不帖了。只给出我的测试结果,由于该问题源于论坛所以我就是用论坛中原来的测试要求。
测试结果:在TextBox中输入int i = 10;点击Button1以后将会在TextBox2中显示出10。
关键字词: