【问题标题】:C# Convert string to if conditionC#将字符串转换为if条件
【发布时间】:2019-07-04 13:50:54
【问题描述】:

是否可以转换字符串

"value > 5 && value <= 10" 

if 语句?

if (value > 5 && value <= 10)
{
   //do something
}

我有条件以字符串形式存储在数据库中,所以它必须是动态转换

【问题讨论】:

  • 不,不是。你必须自己实现这个逻辑。你可以通过 usinf string.Split(" ");并从那里得到你所有的点点滴滴
  • 您真的必须将这些表达式存储为字符串吗?我认为这可以通过反射实现,但效率低下并且可能容易受到注入攻击。如果条件都是a&gt;b &amp; a&lt;=c,可以存储b和c。或者,您可以自己解析字符串(为了简化,您可以将格式更改为更机器可读的格式)。
  • 大多数时候,当有人在做这样的字符串魔术时,实际上有一个更简单的解决方案,也许你可以尝试解释一下——你是如何得到那个字符串的,为什么需要这个?
  • 出于安全考虑,我倾向于不评估客户端派生的 C# 表达式。理想情况下,您需要将其解析为某种形式的 AST,您可以将其转换为表达式或仅使用您自己的代码进行评估。通过这种方式,您可以限制可用的操作类型。更好的是,让上游业务逻辑创建 AST 表示而不是字符串。

标签: c# .net


【解决方案1】:

相反,您可以将其视为 javascript 行,并可以使用 Windows Script Engines 完成此操作,前提是值是真实值而不是变量名。

 if(ScriptEngine.Eval("jscript", "value > 5 && value <= 10"))
   {
     //Your logic
   }

或者,如果它是一个变量,那么您可以构建一个如下所示的 JS 函数来完成此操作:

using (ScriptEngine engine = new ScriptEngine("jscript"))
{
  string JSfunction =  "MyFunc(value){return " + "value > 5 && value <= 10" + "}";

  ParsedScript parsed = engine.Parse(JSfunction);
  if(parsed.CallMethod("MyFunc", 3))
  {  
   // Your Logic
  }
}

【讨论】:

    【解决方案2】:

    您可以使用Linq.Expression 来构建您提供的表达式树:

    "value > 5 && value <= 10"
    
    var val = Expression.Parameter(typeof(int), "x");
    var body = Expression.And(
         Expression.MakeBinary(ExpressionType.GreaterThan, val, Expression.Constant(5)), 
         Expression.MakeBinary(ExpressionType.LessThanOrEqual, val, Expression.Constant(10)));
    
    var lambda = Expression.Lambda<Func<int, bool>>(exp, val);
    bool b = lambda.Compile().Invoke(6); //true
    bool b = lambda.Compile().Invoke(11); //false
    

    这只是一个了解一些想法的示例,您仍然需要一种聪明的方法来解析和构建树。

    【讨论】:

      【解决方案3】:

      使用System.Data.DataTable的Compute方法:

      static class ExpressionHelper
      {
          private static readonly DataTable dt = new DataTable();
          private static readonly Dictionary<string, string> expressionCache = new Dictionary<string, string>();
          private static readonly Dictionary<string, object> resultCache = new Dictionary<string, object>();
      
          // to be amended with necessary transforms
          private static readonly (string old, string @new)[] tokens = new[] { ("&&", "AND"), ("||", "OR") };
      
          public static T Compute<T>(this string expression, params (string name, object value)[] arguments) =>
              (T)Convert.ChangeType(expression.Transform().GetResult(arguments), typeof(T));
      
          private static object GetResult(this string expression, params (string name, object value)[] arguments)
          {
              foreach (var arg in arguments)
                  expression = expression.Replace(arg.name, arg.value.ToString());
      
              if (resultCache.TryGetValue(expression, out var result))
                  return result;
      
              return resultCache[expression] = dt.Compute(expression, string.Empty);
          }
      
          private static string Transform(this string expression)
          {
              if (expressionCache.TryGetValue(expression, out var result))
                  return result;
      
              result = expression;
              foreach (var t in tokens)
                  result = result.Replace(t.old, t.@new);
      
              return expressionCache[expression] = result;
          }
      }
      

      用法

      var expr = "value > 5 && value <= 10";
      var a1 = expr.Compute<bool>(("value", 5)); // false
      var a2 = expr.Compute<bool>(("value", 7)); // true
      var a3 = expr.Compute<bool>(("value", 11)); // false
      

      【讨论】:

        【解决方案4】:

        恐怕您必须为此创建简单的解析器。

        您可以尝试使用FParsec 之类的内容。这是一个 F# 解析器库。我不知道 C# 中有这样的代码

        【讨论】:

        • 这似乎是一个 F# 库。
        • 它是一个 F# 库,仍在 .NET 空间中。
        • 整个教程都在 F# 中。您还没有提供如何在 C# 中使用它的示例,所以我们必须猜测。这目前无法回答问题。
        猜你喜欢
        • 2022-11-23
        • 2019-05-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-03
        相关资源
        最近更新 更多