我想做相当于:

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

关注比里斯 关联, ,我得到了这个片段(修改为删除过时的方法 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;

}  
有帮助吗?

解决方案

通过使用即时编译,例如 这个例子 显示。

或者通过使用 逃跑, ,这是出于完全相同的原因。

其他提示

我写了一个开源项目, 动态浓缩咖啡, ,它可以将使用 C# 语法编写的文本表达式转换为委托(或表达式树)。文本表达式被解析并转换为 表达式树 不使用编译或反射。

你可以这样写:

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 .

老话题,但考虑到这是谷歌搜索时出现的第一个线程,这里是一个更新的解决方案。

您可以使用 Roslyn 用于计算表达式的新脚本 API.

如果您使用 NuGet,只需添加依赖项 Microsoft.CodeAnalysis.CSharp.Scripting。要评估您提供的示例,很简单:

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

这显然没有利用脚本引擎的异步功能。

您还可以根据需要指定评估结果类型:

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

要评估更高级的代码片段、传递参数、提供引用、命名空间等,请检查上面链接的 wiki。

如果您特别想在自己的项目中调用代码和程序集,我建议使用 C# CodeDom CodeProvider.

以下是我所知道的在 C# 中动态计算字符串表达式的最流行方法的列表。

微软解决方案

非微软解决方案(并不是说这有什么问题)

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;
        }
    }
}

这样做对性能有何影响?

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

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

看起来还有一种方法可以使用 RegEx 和 XPathNavigator 来计算表达式。我还没有机会测试它,但我有点喜欢它,因为它不需要在运行时编译代码或使用不可用的库。

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

我会尝试一下,稍后告诉您是否有效。我也打算在Silverlight中尝试一下,但是为时已晚,我现在都快睡着了。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top