如何dynamic评估C#expression式?

我想做相当于:

object result = Eval("1 + 3"); string now = Eval("System.DateTime.Now().ToString()") as string 

继Biri的链接后 ,我得到了这个片段(修改为删除过时的方法ICodeCompiler.CreateCompiler()

 private object Eval(string sExpression) { CSharpCodeProvider c = new CSharpCodeProvider(); CompilerParameters cp = new CompilerParameters(); cp.ReferencedAssemblies.Add("system.dll"); cp.CompilerOptions = "/t:library"; cp.GenerateInMemory = true; StringBuilder sb = new StringBuilder(""); sb.Append("using System;\n"); sb.Append("namespace CSCodeEvaler{ \n"); sb.Append("public class CSCodeEvaler{ \n"); sb.Append("public object EvalCode(){\n"); sb.Append("return " + sExpression + "; \n"); sb.Append("} \n"); sb.Append("} \n"); sb.Append("}\n"); CompilerResults cr = c.CompileAssemblyFromSource(cp, sb.ToString()); if (cr.Errors.Count > 0) { throw new InvalidExpressionException( string.Format("Error ({0}) evaluating: {1}", cr.Errors[0].ErrorText, sExpression)); } System.Reflection.Assembly a = cr.CompiledAssembly; object o = a.CreateInstance("CSCodeEvaler.CSCodeEvaler"); Type t = o.GetType(); MethodInfo mi = t.GetMethod("EvalCode"); object s = mi.Invoke(o, null); return s; } 

通过使用编译,就像这个例子所示。

或者使用Flee ,这是完全一样的原因。

我写了一个开源项目Dynamic Expresso ,它可以将使用C#语法编写的文本expression式转换为委托(或expression式树)。 文本expression式被parsing并转换成expression式树而不使用编译或reflection。

你可以写下如下的东西:

 var interpreter = new Interpreter(); var result = interpreter.Eval("8 / 2 + 2"); 

要么

 var interpreter = new Interpreter() .SetVariable("service", new ServiceExample()); string expression = "x > 4 ? service.aMethod() : service.AnotherMethod()"; Lambda parsedExpression = interpreter.Parse(expression, new Parameter("x", typeof(int))); parsedExpression.Invoke(5); 

我的工作基于Scott Gu的文章http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

老主题,但考虑到这是谷歌search时显示的第一个线程之一,这里是一个更新的解决scheme。

您可以使用Roslyn的新脚本API来评估expression式 。

如果您正在使用NuGet,只需添加一个依赖到Microsoft.CodeAnalysis.CSharp.Scripting 。 为了评估你提供的例子,它很简单:

 var result = CSharpScript.EvaluateAsync("1 + 3").Result; 

这显然不利用脚本引擎的asynchronousfunction。

您也可以按照您的意图指定评估结果types:

 var now = CSharpScript.EvaluateAsync<string>("System.DateTime.Now.ToString()").Result; 

要评估更高级的代码片段,传递参数,提供参考,命名空间和什么,请检查上面链接的维基。

 using System; using Microsoft.JScript; using Microsoft.JScript.Vsa; using Convert = Microsoft.JScript.Convert; namespace System { public class MathEvaluator : INeedEngine { private VsaEngine vsaEngine; public virtual String Evaluate(string expr) { var engine = (INeedEngine)this; var result = Eval.JScriptEvaluate(expr, engine.GetEngine()); return Convert.ToString(result, true); } VsaEngine INeedEngine.GetEngine() { vsaEngine = vsaEngine ?? VsaEngine.CreateEngineWithType(this.GetType().TypeHandle); return vsaEngine; } void INeedEngine.SetEngine(VsaEngine engine) { vsaEngine = engine; } } } 

尽pipeC#本身并不支持Eval方法,但我有一个C#eval程序,它允许评估C#代码。 它提供了在运行时评估C#代码并支持许多C#语句。 实际上,这个代码在任何.NET项目中都是可用的,但是它仅限于使用C#语法。 看看我的网站http://csharp-eval.com ,了解更多详情。

这样做的性能影响是什么?

我们使用基于上述类似的系统,其中每个C#脚本都被编译为内存中的程序集,并在单独的AppDomain中执行。 目前还没有caching系统,所以脚本每次运行都要重新编译。 我做了一些简单的testing,在我的机器上大约0.7秒内编译了一个非常简单的“Hello World”脚本,包括从磁盘加载脚本。 对于脚本系统来说,0.7秒是正确的,但是对于用户input的响应可能太慢,在这种情况下,像Flee这样的专用parsing器/编译器可能会更好。

 using System; public class Test { static public void DoStuff( Scripting.IJob Job) { Console.WriteLine( "Heps" ); } } 

看起来还有一种使用RegEx和XPathNavigator来评估expression式的方法。 我没有机会testing它,但我有点喜欢它,因为它不需要在运行时编译代码或使用无法使用的库。

http://www.webtips.co.in/c/evaluate-function-in-c-net-as-eval-function-in-javascript.aspx

我会尝试一下,然后告诉它是否工作。 我也打算在Silverlight中试用,但已经太晚了,现在我几乎已经睡着了。