.NET Core中如何不使用eval()将带变量的字符串转换为可计算数学表达式
实现方案
方案1:基于.NET 原生表达式树实现(无第三方依赖)
直接用System.Linq.Expressions命名空间下的表达式树能力,解析字符串后构建可执行委托,完全规避eval类实现。
你需要先将表达式用到的变量(如示例中的total)注册为表达式参数,对输入的字符串做词法拆分识别出数字、变量名、运算符后,按运算优先级构建表达式树,最后编译为委托调用即可。
核心示例代码:
using System.Linq.Expressions; using System.Collections.Generic; public static class CustomExpressionCalculator { public static decimal Calculate(string expression, Dictionary<string, decimal> variableContext) { // 常量表达式直接返回 if (decimal.TryParse(expression, out var constantVal)) { return constantVal; } // 注册变量参数 var totalParam = Expression.Parameter(typeof(decimal), "total"); Expression body; // 此处可根据需要扩展解析逻辑,示例适配你当前的"total*2/100"场景 // 扩展时可先将表达式转为逆波兰式处理运算优先级、括号等场景 body = Expression.Divide( Expression.Multiply(totalParam, Expression.Constant(2m)), Expression.Constant(100m) ); // 编译为可执行委托 var calcFunc = Expression.Lambda<Func<decimal, decimal>>(body, totalParam).Compile(); return calcFunc(variableContext["total"]); } } // 业务层调用示例 decimal total = 200m; string varExpression = "total*2/100"; var context = new Dictionary<string, decimal> { { "total", total } }; // 替换你原来的total = total + var逻辑 total += CustomExpressionCalculator.Calculate(varExpression, context);
后续扩展更多表达式格式时,只需完善词法解析部分,支持更多运算符、自定义函数都可以通过扩展表达式树的构建逻辑实现。
方案2:手写递归下降解析器
如果后续有大量自定义业务规则的扩展需求,可以自己实现轻量解析器,步骤如下:
- 词法分析:将输入字符串拆分为token序列,分类为数字、变量名、运算符、括号等类型
- 语法分析:按照运算优先级(括号>乘除>加减)构建抽象语法树
- 遍历语法树,从上下文读取变量值执行计算
这种方式完全可控,没有任何依赖,适配性最强。
注意要点
- 所有运算统一用
decimal类型处理,避免浮点精度丢失,匹配你当前的变量类型定义 - 提前做表达式合法性校验,避免非法表达式运行时报错,建议补充单元测试覆盖所有支持的表达式格式
- 处理带括号、嵌套运算的场景时,优先用逆波兰式转换处理运算优先级,避免逻辑混乱
内容的提问来源于stack exchange,提问作者Marco Leone
相关产品推荐
相关产品推荐

