C# 如何对字符串公式执行计算?

对字符串公式的执行计算,在规则策略中比较常见,常用于定制化的场景下,比如:定制下单价格计算、定制监控参数计算等等。对于 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# 如何对字符串公式执行计算?》的相关评论

发表评论

必填项已用 * 标记,邮箱地址不会被公开。