如何动态计算C#表达式?

如何动态计算C#表达式?,c#,reflection,eval,C#,Reflection,Eval,我想做的工作相当于: object result = Eval("1 + 3"); string now = Eval("System.DateTime.Now().ToString()") as string 在Biri之后,我得到了这个代码段(修改为删除过时的方法ICodeCompiler.CreateCompiler(): 这样做对性能有什么影响 我们使用一个基于上述内容的系统,其中每个C#脚本被编译成内存中的程序集,并在一个单独的AppDomain中执行。目前还没有缓存系统,所以

我想做的工作相当于:

object result = Eval("1 + 3");
string now    = Eval("System.DateTime.Now().ToString()") as string
在Biri之后,我得到了这个代码段(修改为删除过时的方法
ICodeCompiler.CreateCompiler()

这样做对性能有什么影响

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

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

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


我将尝试一下,稍后再告诉它是否有效。我也打算在Silverlight中尝试,但现在做已经太迟了,我几乎睡着了。

虽然C#本机不支持Eval方法,但我有一个C#Eval程序,它允许评估C#代码。它提供在运行时评估C#代码,并支持许多C#语句s、 事实上,此代码在任何.NET项目中都是可用的,但是,它仅限于使用C#语法。有关更多详细信息,请查看我的网站。

我编写了一个开源项目,可以将使用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;
        }
    }
}
你可以这样写:

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


我的工作基于Scott Gu的文章。

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

你可以用

如果您使用的是NuGet,只需将依赖项添加到。 要评估您提供的示例,只需执行以下操作:

var result = CSharpScript.EvaluateAsync("1 + 3").Result;
这显然没有利用脚本引擎的异步功能

还可以根据需要指定计算结果类型:

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

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

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

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

微软解决方案
  • :
    • 看到了吗
  • :
    • 看到这个和这个了吗
  • :
    • 看到这个了吗
    • 看到这个了吗
    • 看到和
  • 正在执行PowerShell:
非Microsoft解决方案(并不是说这有什么问题)
  • 表达式计算库:
  • Javascript解释器
  • 执行实C#
  • 推出您自己的语言构建工具包,如:

有一个更好的JavaScript实现,名为Iron JS。它使用了类似Iron Python等DLR。据我所知,Vsa已经过时,除非您在单独的AppDomain中编译和执行,否则可能会遇到内存问题。以这种方式生成的程序集无法卸载,但如果您在se中创建程序集Operate AppDomain您可以卸载AppDomain,从而卸载生成的程序集。为什么有必要这样做?我非常怀疑这是出于您的任何目的的最佳设计。很可能有其他机制可以在不打开大量蠕虫的情况下产生您想要的结果(为了安全性和可维护性)这就是在运行时评估代码片段。我想要一种快速而肮脏的方法,将表达式验证添加到我编写的DSL中。我控制输入到评估器的文件,因此永远不会打开蠕虫的罐头;)此外,我只允许一个表达式,不添加任何名称空间/引用任何程序集。这也应该阻止我自己做坏事!我在测试场景中这样做。我有一个程序集,它在更新时更改版本号。我希望我的测试代码“后期绑定”到程序集,以便能够加载程序集并动态调用它。这是一个简单的思考问题。但是,当我想要实现在程序集中指定的接口时,它需要动态编译代码,因为接口本身具有强名称(带有版本号)。当我想调用v1.3时,我不能有实现ifoov1.2的代码。动态编译解决了这个问题。我应该说,还有很多其他的场景。这不是主流做法,但在很多情况下,动态代码编译是有意义的。+1@Davide lcardi这是一个非常好的库,但有一些限制:我喜欢这个功能,而且工作得非常好。唯一的抱怨是它太慢了,太慢了。添加30秒来评估简单表达式似乎您遗漏了一些选项(在这里的其他答案中有一些选项),例如
DataColumn.Expression
DataTable.Compute
以及不推荐使用的JScript。
var result = CSharpScript.EvaluateAsync("1 + 3").Result;
var now = CSharpScript.EvaluateAsync<string>("System.DateTime.Now.ToString()").Result;