对字符串公式的执行计算,在规则策略中比较常见,常用于定制化的场景下,比如:定制下单价格计算、定制监控参数计算等等。对于 C# 计算字符串公式,大多数用法是调用 JS 计算或者是使用 DataTable 的 Compute()。但 C# 调用 JS 计算字符串公式效率低,并不推荐。而 DataTable 的 Compute() 比较局限于DataTable,并不能应对灵活的计算公式。本文将推荐另一种比较高效的且灵活的字符串公式计算利器——Flee。
Flee 是 .NET 框架的表达式解析器和评估器,允许你在运行时计算诸如sqrt(a^2+b^2)
之类的字符串表达式的值。 它使用自定义编译器、强类型表达式语言和轻量级代码生成器,将表达式直接编译到 IL。这意味着表达式计算非常快速高效。Flee 开源地址为:https://github.com/mparlak/Flee。
在使用之前需要通过 Nuget 安装 Flee:
Install-Package Flee
假设有以下这个字符串表达式,我们现在来看一下如何使用 C# 执行计算。
If(("LongTextToPushScriptLengthOver256CharactersJustToMakeSureItDoesntMatter")="C", (If(("D")="E", 2, 3)), (If(("D")="E", Floor((((((4000)/46.228)+8 )*46.228)*3)+5126)+1471/304.8+20, Floor(((((((((4000)/46.228)+8 )*46.228)*3)+5126)+1217)/304.8)+20) ) ) )
上述字符串表达式中,不仅有If
的三元运算符,还有Floor
这个.NET中的数学计算函数。从 IF 和 Floor 在表达式的应用可以看到,字符串公式的灵活和强大之处,适用的场景非常广阔。由于这个字符串表达式较长,为了编码方便,可先将其保存在 js 或 txt 文档中,供后续计算程序调取。
那么,这个字符串表达式到底如何使用 C# 执行计算呢?为了节省篇幅,以下提供关键部分代码:
using Flee.CalcEngine.PublicTypes; using Flee.PublicTypes; using System; using System.IO; namespace IO.Pzy.Flee.Demo { public class FormulaFunctions { private readonly SimpleCalcEngine _engine; public FormulaFunctions() { //实例化计算引擎 var engine = new SimpleCalcEngine(); //实例化表达式上下文 var context = new ExpressionContext(); //添加数学计算类 context.Imports.AddType(typeof(Math)); context.Imports.AddType(typeof(Convert)); engine.Context = context; _engine = engine; } /// <summary> /// 执行公式计算 /// </summary> /// <returns></returns> public double CalFormula() { var script1 = File.ReadAllText("formulaText.js"); var expr = _engine.Context.CompileDynamic(script1); var result = (double)expr.Evaluate(); return result; } } }
其中formulaText.js
为前述字符串公式存放的文件名,从文件中加载公式然后执行计算。需要注意的是,当在代码中生成字符串表达式时,根据我的使用经验,对于 If 运算符中的条件判断,条件等号两端的数据类型要一致,对于字符串的判断,需要添加引号并转义,否则会报错。另外,判断“不等于”不能使用<>
,只能用!=
。至于原因,可联想一下 C# 的语法,Flee 其实就是对类 C# 语句进行动态编译执行。
除此之外,Flee 还可以执行C#定义的方法,例如,我们定义了以下 C# 计算方法:
public static class PriceFunctions { public static decimal Calc(string code, decimal x) { if (code == "a") { return x * 100; } if (code == "b") { return x * 500; } return x + 50; } }
如果要使用 Flee 执行定义的该 C# 方法,可参考以下用法:
static void CalcFuction() { var context = new ExpressionContext(); context.Imports.AddType(typeof(PriceFunctions)); context.Variables.Add("code", "x"); context.Variables.Add("x", 100); var de = context.CompileDynamic("calc(code,x)"); var result = (decimal)de.Evaluate(); Console.WriteLine("Result:{0}", result); }
个性化定制时代,字符串公式计算在 IT 系统中的应用,将越来越广泛,也越来越深入。
《 C# 如何对字符串公式执行计算?》的相关评论