回答

收藏

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

技术问答 技术问答 187 人阅读 | 0 人回复 | 2023-09-14

我的.NET应用程序在运行时评估用户定义的规则。这些规则由用户通过GUI菜单输入到系统中。我生成一个与其对应的逻辑语句,并将其存储在数据库中。* Q/ W% @# Y6 e: @% ]! s
例如:(名称=’John’AND姓氏=’Smith’)或数字> 126 w/ ]* u/ C# w$ h1 f
但是,当用户想要通过GUI编辑规则时,我需要进行反向操作来从存储的规则中确定菜单状态,这既昂贵又复杂。您如何建议以一种可以轻松地反转到菜单状态的方式存储规则?
' Q. U8 u; I5 T                * V$ p( X6 E8 ~% R$ n) J
解决方案:
6 n  ]. T% [( B  |+ m               
( l' G2 A6 Z5 F( ~: H
& X% Z. H6 k& z' ]4 K7 b  S6 m! }% d% x
                您可以将规则存储为AST-实现一些表示树节点的类:
% f5 z$ j' l  e2 `interface INode3 S5 A. p2 F. k9 o+ c# x: A4 A
{; s. I9 q3 x3 }$ i' t4 s7 a
}5 O1 S" A4 Z  {0 s+ e6 ~! _, t
enum BinaryOperator
& l( f% O% j( V{
, B, e4 j8 k3 J8 ~    AND, OR, Equal, Greater, Lower;
+ K) L$ k! o. |( O* B}
! m0 g. j* ~9 v& L. x' Sclass BinaryExpression : INode
" V$ M4 |3 z" E3 Q9 p{/ A* u9 E2 G' N6 g2 a
    BinaryOperator Operator { get; set; }
8 A' _+ D" }, X$ B: Y2 C    INode Left { get; set; }
# w" W$ S0 S# p8 o" Z6 E( r) I, k# V    INode Right { get; set; }
0 t1 g" `2 W7 w}8 N. C( M3 w2 V5 f) `/ }, ^& }. k% z- S
class PropertyRerefence : INode
* ~9 b( E# K. B+ r# X$ }, `- \{* m! g  W' _3 Z8 i* f- f( Z. Z1 f
    string PropertyName { get; set; }( f" g: J# x' ^0 M% Q
}: g( z9 @, ^4 o. b( \1 \5 E- t
class Constant : INode
0 j1 K9 T7 }4 R, T; r$ t{& V9 \' ^" j! J1 I" P# t
    string Value { get; set; }6 l! }7 ~3 r# H+ s# M
}
! ?  F# y& e! O/ G5 Y, j$ j您的示例树如下所示:
1 _) l, K. f* M/ nBinaryExpression(OR)8 ^: M8 t& V7 s/ R- q  g
  Left=BinaryExpression(AND)
5 Z7 y- a8 e/ X. f          Left=...
4 d1 Z0 @- m! w, c, x; K          Right=...9 V; K2 l" s/ E8 s/ A
  Right=BinaryExpression(Greater)
, j; e. d) |: |          Left=PropertyReference("Number")
8 t0 h3 \1 \! r; A# h9 `& B          Right=Constant("12")
( G3 q2 S2 _0 Z0 }然后,您可以使用序列化(最好的JSON或XML,如果您不关心db的可读性,甚至可以使用二进制)来保存此类树。反序列化时,您无需进行任何解析,就可以遍历树来填充菜单。
$ l& N9 g. R5 z" x使用AST时,也很容易打印“(名称=’John’AND姓氏=’Smith’)或数字>6 j& f, R, Z5 y# Z; M- q+ A
12”-对于BinaryExpression:向左打印,向右打印操作符,向右打印。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则