如何在C#中运行时评估任意布尔字符串表达式?
解决方案
方案1:修正NCalc表达式的字符串字面量格式
NCalc默认用单引号包裹字符串字面量,双引号会被解析为其他语法,导致未加引号的标识符被判定为未定义参数。你可以:
- 直接将表达式中的双引号替换为单引号:
string filterExpression = "'GEN'=='GEN' || 'GEN'=='GENINTER'"; var e = new NCalc.Expression(filterExpression, NCalc.EvaluateOptions.IgnoreCase); bool filterResult = (bool)e.Evaluate();
- 如果输入是C#风格的双引号表达式,先做字符串替换再传入NCalc:
string csharpExpr = "\"GEN\"==\"GEN\" || \"GEN\"==\"GENINTER\""; string ncalcExpr = csharpExpr.Replace("\"", "'"); var e = new NCalc.Expression(ncalcExpr, NCalc.EvaluateOptions.IgnoreCase); bool result = (bool)e.Evaluate();
方案2:自定义NCalc的参数解析逻辑
如果不想修改表达式格式,可通过EvaluateParameter事件将未定义的标识符直接作为字符串字面量返回:
string filterExpression = "GEN==\"GEN\" || \"GEN\"==\"GENINTER\""; var e = new NCalc.Expression(filterExpression, NCalc.EvaluateOptions.IgnoreCase); e.EvaluateParameter += (name, args) => args.Result = name; bool result = (bool)e.Evaluate();
此方法会把所有未定义的参数名称当作字符串值传入计算,匹配你的需求场景。
方案3:使用Roslyn直接编译执行C#表达式
由于你的输入是合法的C#布尔表达式,用Roslyn可以原生支持C#语法,无需调整表达式格式:
- 先安装NuGet包
Microsoft.CodeAnalysis.CSharp - 实现动态评估方法:
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using System; using System.Reflection; using System.Linq; public static bool EvaluateCSharpBoolExpr(string expression) { var code = $@" public static class ExprEval {{ public static bool Run() => {expression}; }}"; var syntaxTree = CSharpSyntaxTree.ParseText(code); var assemblyName = Guid.NewGuid().ToString(); var references = new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location), MetadataReference.CreateFromFile(typeof(string).Assembly.Location) }; var compilation = CSharpCompilation.Create( assemblyName, new[] { syntaxTree }, references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); using var ms = new System.IO.MemoryStream(); var emitResult = compilation.Emit(ms); if (!emitResult.Success) { var errors = string.Join("\n", emitResult.Diagnostics.Select(d => d.GetMessage())); throw new InvalidOperationException($"编译失败:{errors}"); } ms.Position = 0; var assembly = Assembly.Load(ms.ToArray()); var evalType = assembly.GetType("ExprEval"); var evalMethod = evalType.GetMethod("Run"); return (bool)evalMethod.Invoke(null, null); }
使用示例:
string expr = "(\"ASDF\"==\"A\" || \"BED\"!=\"BED\") && (5>=2)"; bool result = EvaluateCSharpBoolExpr(expr);
该方案完全兼容C#语法,适合运行时动态评估任意合法C#布尔表达式的场景。
内容的提问来源于stack exchange,提问作者Greg W
相关产品推荐
相关产品推荐

