规则引擎 - 如何存储规则以避免编辑时解析?

发布于 2024-11-16 14:28:05 字数 217 浏览 9 评论 0原文

我的 .NET 应用程序在运行时评估用户定义的规则。这些规则由用户通过 GUI 菜单输入系统。我生成一个与其对应的逻辑语句并将其存储在数据库中。

例如:(姓名 = '约翰' AND 姓氏 = '史密斯') OR 号码 > 12

然而,当用户想要通过GUI编辑规则时,我需要进行反向操作来从存储的规则中确定菜单状态,这是昂贵且复杂的。您建议如何以可以轻松反转为菜单状态的方式存储规则?

My .NET application evaluates user defined rules at runtime. These rules are entered to system via GUI menus by user. I generate a logical statement that corresponds to it and store it in database.

For example: (Name = 'John' AND Surname = 'Smith') OR Number > 12

However, when the user wants to edit a rule by GUI, I need to make a reverse operation to determine menu states from the stored rule, which is costly and complex. How would you recommend to store rules in a way that it can be reversed to menu states easily?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

断肠人 2024-11-23 14:28:05

您可以将规则存储为 AST - 实现一些表示树节点的类:

interface INode
{
}

enum BinaryOperator 
{
    AND, OR, Equal, Greater, Lower;
}

class BinaryExpression : INode
{
    BinaryOperator Operator { get; set; }
    INode Left { get; set; }
    INode Right { get; set; } 
}

class PropertyRerefence : INode
{
    string PropertyName { get; set; }
}

class Constant : INode
{
    string Value { get; set; }
}

您的示例的树如下所示:

BinaryExpression(OR)
  Left=BinaryExpression(AND)
          Left=...
          Right=...
  Right=BinaryExpression(Greater)
          Left=PropertyReference("Number")
          Right=Constant("12")

然后您可以使用序列化(最好的 JSON 或 XML,如果您不关心数据库中的可读性,甚至可以使用二进制)来保存此类树。在反序列化时,您不需要进行任何解析,并且可以遍历树来填充菜单。

当您拥有 AST 时,打印“(Name = 'John' AND Surname = 'Smith') OR Number > 12”也很容易 - 对于 BinaryExpression:print Left,print Operator,print Right。

您说您已经实施了评估,所以我将忽略这一点。您还可以查看此问题

You could store the rules as ASTs - implement a few classes that represent the nodes of the tree:

interface INode
{
}

enum BinaryOperator 
{
    AND, OR, Equal, Greater, Lower;
}

class BinaryExpression : INode
{
    BinaryOperator Operator { get; set; }
    INode Left { get; set; }
    INode Right { get; set; } 
}

class PropertyRerefence : INode
{
    string PropertyName { get; set; }
}

class Constant : INode
{
    string Value { get; set; }
}

The tree for your example would look like this:

BinaryExpression(OR)
  Left=BinaryExpression(AND)
          Left=...
          Right=...
  Right=BinaryExpression(Greater)
          Left=PropertyReference("Number")
          Right=Constant("12")

You could then use serialization (best JSON, or XML, maybe even binary if you don't care about readability in the db) to save such trees. On deserialization, you don't need to do any parsing and can traverse the tree to populate the menus.

Printing "(Name = 'John' AND Surname = 'Smith') OR Number > 12" is also easy when you have the AST - for a BinaryExpression: print Left, print Operator, print Right.

You say you already have the evaluation implemented so I'll leave this out. You can also look at this question.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文