我在数据库中有一些列包含HH:MM
格式的时间。现在,如果有像11:00 - 12:00
这样的简单表达式,那么我可以轻松地在C#中创建一个名为SubtractTime
的扩展方法,并在运行时传递我的参数。我将我的公式存储在数据库中,例如:
Condition Value
ExamTimeRemaing > 10:00 SubtractTime(Original,Remaining)
现在在上面的例子中,我可以在运行时使用反射调用我的SubtractTime
函数,但是我的问题是这样,如果我的表达式变得复杂如下:
10:00 + 12:00 * 00:02 - 10:11
我如何解析这些表达式?我不需要编码方面的帮助,因为我已经有了将时间转换为刻度然后转换为HH:MM
的扩展。这更像是一个设计问题。我想要一个可扩展的解决方案,以便我可以有效地创建规则引擎。
答案 0 :(得分:0)
我想说将它存储为字符串并找到运算符。创建一个递归函数ParseAndCalc(字符串输入),它以正确的顺序解析和计算结果。像这样:
double ParseAndCalc(string input)
{
string[] sub;
double result = 0;
if(input.Contains("+"))
{
sub = input.Split('+');
foreach(string substring in sub)
{
result += ParseAndCalc(substring);
}
}
else if (input.Contains("-"))
{
sub = input.Split('-');
foreach(string substring in sub)
{
result -= ParseAndCalc(substring);
}
}
else if (input.Contains("*"))
{
sub = input.Split('*');
foreach(string substring in sub)
{
result *= ParseAndCalc(substring);
}
}
else if (input.Contains("/"))
{
sub = input.Split('/');
foreach(string substring in sub)
{
double parsed = ParseAndCalc(substring);
if(parsed != 0)
{
result /= ParseAndCalc(substring);
}
else
{
// Error
}
}
}
return result;
}
答案 1 :(得分:0)
首先,您必须考虑开发和维护开销。使用Antlr等创建表达式解析器是绝对荒谬的,我会使用像Jurassic这样的JavaScript引擎或任何其他基于.NET的简单JavaScript引擎这样的现成解决方案。
SQL存储过程/用户定义函数
此外,如果您的规则存储在数据库本身中,那么您可以使用SQL本身的功能来解析和计算表达式,而不是使用解析器。您可以动态组合SQL表达式并传递参数。或者创建存储过程或用户定义的函数,这些函数经过良好测试,众所周知且可扩展,并且保持在数据库的上下文中。
开源.NET JavaScript引擎
您仍然可以使用JavaScript格式将公式存储在数据库中,首先,JavaScript是众所周知的,易于理解并且能够处理复杂的表达式。有许多免费且稳定的JavaScript引擎,它提供丰富的语言功能,您仍然可以在公式中使用现有的JavaScript库。例如,将来你需要Base64,你只需从一些github获取Base64并将它放在你的JavaScript中。
C#编译器
CSharpCompilerProvider类为您提供了一种将C#源编译成程序集的方法,我要做的是使用一些文本模板创建源文件,在SQL中编译和存储程序集以及formulat,当我需要调用表达式时,我可以获取编译版本,使用Assembly.Load
加载它并创建具有一些接口并调用它的方法的解析类。 .NET将编译并为您提供程序集,您可以将其作为varbinary(max)
存储在数据库中。
答案 2 :(得分:0)
这里的答案告诉你如何做得这么好。如果你决定尝试这个,我可能会自己选择ANTLR路线。
那就是说,我会认真思考为什么要这样做。你提到你正在建立一个“规则引擎”。从这里开始,我假设您有一个数据库或者您想要将一堆业务逻辑存储为“规则”的东西,然后让“规则引擎”读取这个并将其应用于某些数据。作为其中的一部分,您希望某种表达式解析器能够解析和评估某些类型的规则。
在查看这样的设计时,我会小心不要混淆解析规则和执行它们的问题。您可以使用XML,JSON或您喜欢的任何内容格式对规则进行编码。如果这样做,您根本不必编写解析器。你只需评估表达式。
var myRule = [
{ $value: '10:00' },
{ $add: '12:00' },
{ $multiply: 2 },
{ $subtract: '10:11' }
]