在运行时评估表达式

发布于 2024-10-11 00:27:49 字数 204 浏览 7 评论 0原文

我有一个 C# 控制台应用程序项目。

我有一个逻辑表达式作为 nvarchar 存储在数据库中。

例如,存储的表达式为:((34>0)||(US==ES))&& (4312 = 5691)

当我的应用程序运行时,我想检索表达式并对其求值,以便结果为 true 或 false。

我怎样才能在运行时做到这一点?

I have a C# Console Application project.

I have a logical expression that is stored in database as nvarchar.

For example, the stored expression is: ((34 > 0) || (US == ES)) && (4312 = 5691)

While my application running, I want to retrieve the expression and evaluate it so that the result will be true or false.

How can I do it at runtime?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

陈甜 2024-10-18 00:27:49

这是一个相当不寻常的解决方案,涉及 JScript:

  • 使用以下代码创建一个 JScript 类:

    公共类 JsMath {
        公共静态函数 Eval(表达式:String) : 对象 {
            返回 eval( 表达式 );
        }
    }
    
  • 将其编译为 DLL:

    jsc /target:library /out:JsMath.dll JsMath.js
    
  • 在您的 C# 项目中,引用 JsMath.dll 和 Microsoft.JScript.dll

  • 现在您可以使用 Eval 方法,如下所示:

    字符串表达式 = "((34 > 0) || ('US' == 'ES')) && (4312 == 5691)";
    布尔结果 = (bool)JsMath.Eval(表达式);
    

优点:

  • 无需解析表达式,JScript 引擎会为您完成此操作,
  • 无需编译任意代码(这如果代码是由用户输入的,则可能是一个很大的安全漏洞)
  • 应该适用于任何简单的数学或逻辑表达式,只要它遵循 JScript 语法

缺点:

  • 无法传递变量(据我所知)
  • 需要引用JScript 程序集(在大多数情况下不是一个大问题,但我不确定该程序集在客户端配置文件或 Silverlight 中是否可用)

Here's a rather unusual solution, involving JScript:

  • Create a JScript class with the following code:

    public class JsMath {
        public static function Eval(expression:String) : Object {
            return eval(expression);
        }
    }
    
  • Compile it into a DLL:

    jsc /target:library /out:JsMath.dll JsMath.js
    
  • In your C# project, reference JsMath.dll and Microsoft.JScript.dll

  • Now you can use the Eval method as follows:

    string expression = "((34 > 0) || ('US' == 'ES')) && (4312 == 5691)";
    bool result = (bool)JsMath.Eval(expression);
    

Benefits:

  • no work required to parse the expression, the JScript engine does it for you
  • no need to compile arbitrary code (which can be a big security hole if the code is entered by the user)
  • should work with any simple mathematical or logical expression, as long as it follows the JScript syntax

Drawbacks:

  • no way to pass variables (as far as I know)
  • requires a reference to the JScript assembly (not a big issue in most cases, but I'm not sure this assembly is available in the Client Profile or in Silverlight)
暖阳 2024-10-18 00:27:49

您可以将表达式解析为 .NET 表达式 类并编译并运行它以获得结果。

该类已经支持示例中的所有逻辑操作,尽管它看起来不明确(您以非常相似的方式使用 === )。

不过,您必须编写自己的解析器/转换器。

You can parse the expression into the .NET Expression class and compile and run it in order to get the result.

The class already supports all the logical operations you have in your example, though it appears to be ambiguous (you are using both == and = in a very similar manner).

You will have to write your own parser/converter though.

本王不退位尔等都是臣 2024-10-18 00:27:49

我从这里编写了 K. Scott Allen 的 JScript 内联 Eval 调用程序的更紧凑、更高效的版本 (https:/ /odetocode.com/articles/80.aspx):

using System;
using System.CodeDom.Compiler;
using Microsoft.JScript;

class JS
{
    private delegate object EvalDelegate(String expr);
    private static EvalDelegate moEvalDelegate = null;

    public static object Eval(string expr)
    {
        return moEvalDelegate(expr);
    }

    public static T Eval<T>(string expr)
    {
        return (T)Eval(expr);
    }

    public static void Prepare()
    {
    }

    static JS()
    {
        const string csJScriptSource = @"package _{ class _{ static function __(e) : Object { return eval(e); }}}";
        var loParameters = new CompilerParameters() { GenerateInMemory = true };
        var loMethod = (new JScriptCodeProvider()).CompileAssemblyFromSource(loParameters, csJScriptSource).CompiledAssembly.GetType("_._").GetMethod("__");
        moEvalDelegate = (EvalDelegate)Delegate.CreateDelegate(typeof(EvalDelegate), loMethod);
    }
}

只需像这样使用它:

JS.Eval<Double>("1 + 4 + 5 / 99");

返回:

5.05050505050505

如果您愿意,您也可以扩展它以传递变量值,例如传递名称和名称的字典。价值观。第一次使用静态类将花费 100-200 毫秒,之后几乎是瞬时的,并且不需要单独的 DLL。如果需要,可以调用 JS.Prepare() 进行预编译以停止初始延迟。

I have written a more compact and efficient version of K. Scott Allen's JScript inline Eval caller from here (https://odetocode.com/articles/80.aspx):

using System;
using System.CodeDom.Compiler;
using Microsoft.JScript;

class JS
{
    private delegate object EvalDelegate(String expr);
    private static EvalDelegate moEvalDelegate = null;

    public static object Eval(string expr)
    {
        return moEvalDelegate(expr);
    }

    public static T Eval<T>(string expr)
    {
        return (T)Eval(expr);
    }

    public static void Prepare()
    {
    }

    static JS()
    {
        const string csJScriptSource = @"package _{ class _{ static function __(e) : Object { return eval(e); }}}";
        var loParameters = new CompilerParameters() { GenerateInMemory = true };
        var loMethod = (new JScriptCodeProvider()).CompileAssemblyFromSource(loParameters, csJScriptSource).CompiledAssembly.GetType("_._").GetMethod("__");
        moEvalDelegate = (EvalDelegate)Delegate.CreateDelegate(typeof(EvalDelegate), loMethod);
    }
}

Just use it like this:

JS.Eval<Double>("1 + 4 + 5 / 99");

Returns:

5.05050505050505

You could extend it to pass in variable values as well if you wanted to, e.g. pass in a dictionary of names & values. First usage of the static class will take 100-200ms, after that its pretty much instantaneous and doesn't require a separate DLL. Call JS.Prepare() to pre compile to stop the initial delay if you want.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文