规则引擎由推理引擎发展而来,是一种嵌入在应用程序中的组件,实现了将业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策。接受数据输入,解释业务规则,并根据业务规则做出业务决策。应用背景: 企业级管理者对企业IT系统的开发有着如下的要求:
1. 为提高效率,管理流程必须自动化,即使现代商业规则异常复杂。
2. 市场要求业务规则经常变化,IT系统必须依据业务规则的变化快速、低成本的更新。
3. 为了快速、低成本的更新,业务人员应能直接管理IT系统中的规则,不需要程序开发人员参与。
下面介绍一个开源的引擎(NXBRE Rule-engine)实现动态折扣价格计算:
折扣逻辑配置使用XML(扩展名.xbre)为文件,后期修改XML打折策略,在程序代码无需修改的情况,实现柔性折扣策略的目的。
折扣规则文件:discount.xbre
1 <?xml version="1.0" encoding="UTF-8"?> 2 <xBusinessRules xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="xBusinessRules.xsd"> 3 <!-- 全局变量--> 4 <Integer id="10i" value="10"/> 5 <Integer id="40i" value="40"/> 6 <ObjectLookup id="QuantityOrdered" objectId="CurrentOrder" member="Quantity"/> 7 <Logic> 8 <If> 9 <And> 10 <GreaterThanEqualTo leftId="ClientRating" rightId="ClientRatingThreshold"> 11 <!-- CurrentOrder为订单对象--> 12 <ObjectLookup id="ClientRating" objectId="CurrentOrder" member="ClientRating"/> 13 <String id="ClientRatingThreshold" value="C"/> 14 </GreaterThanEqualTo> 15 </And> 16 <Do> 17 <!-- 对于评分高的客户指定的折扣策略 Discount rules for high rate customers --> 18 <Logic> 19 <If> 20 <And> 21 <GreaterThan leftId="QuantityOrdered" rightId="40i"/> 22 </And> 23 <Do> 24 <!-- AppliedDiscount为应用的折扣--> 25 <Evaluate id="AppliedDiscount"> 26 <!-- Percent为折扣比例--> 27 <Parameter name="Percent" value=".7"/> 28 </Evaluate> 29 </Do> 30 </If> 31 <ElseIf> 32 <And> 33 <GreaterThan leftId="QuantityOrdered" rightId="10i"/> 34 </And> 35 <Do> 36 <Evaluate id="AppliedDiscount"> 37 <Parameter name="Percent" value=".8"/> 38 </Evaluate> 39 </Do> 40 </ElseIf> 41 <Else> 42 <Evaluate id="AppliedDiscount"> 43 <Parameter name="Percent" value=".9"/> 44 </Evaluate> 45 </Else> 46 </Logic> 47 </Do> 48 </If> 49 <Else> 50 <!-- 对于评分低的客户指定的折扣策略 Discount rules for low rate customers --> 51 <Logic> 52 <If> 53 <And> 54 <GreaterThan leftId="QuantityOrdered" rightId="40i"/> 55 </And> 56 <Do> 57 <Evaluate id="AppliedDiscount"> 58 <Parameter name="Percent" value=".9"/> 59 </Evaluate> 60 </Do> 61 </If> 62 <Else> 63 <Evaluate id="AppliedDiscount"> 64 <Parameter name="Percent" value="1"/> 65 </Evaluate> 66 </Else> 67 </Logic> 68 </Else> 69 </Logic> 70 </xBusinessRules>
所有的业务逻辑都在discount.xbre 中定义,下面我们定义一个窗体来解析折扣逻辑并显示计算的结果:
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Windows.Forms; 10 using System.Collections; 11 using NxBRE.FlowEngine; 12 using NxBRE.FlowEngine.IO; 13 using BREFactory = NxBRE.FlowEngine.Factories.BREFactory; 14 using Reflection = NxBRE.Util.Reflection; 15 namespace WinApp 16 { 17 public partial class frmDiscountRBE : Form 18 { 19 public frmDiscountRBE() 20 { 21 InitializeComponent(); 22 23 } 24 25 /// <summary> 26 /// 规则xml文件名称 27 /// </summary> 28 public const string FLOW_RULES_FILENAME = "discount.xbre"; 29 public const string ORDER = "CurrentOrder"; 30 public const string APPLIED_DISCOUNT = "AppliedDiscount"; 31 public const string PERCENT = "Percent"; 32 /**/ 33 /// <summary> 34 /// 定单 35 /// </summary> 36 struct Order 37 { 38 public Int32 Quantity; 39 public Double TotalCost; 40 public string ClientRating; 41 public Order(int _q, double _t, string _c) 42 { 43 this.Quantity = _q; 44 this.TotalCost = _t; 45 this.ClientRating = _c; 46 } 47 } 48 /**/ 49 /// <summary> 50 /// 计算结果 51 /// </summary> 52 /// <param name="aBRC">规则引挚上下文</param> 53 /// <param name="aMap"></param> 54 /// <param name="aStep"></param> 55 /// <returns>结果</returns> 56 static object AppliedDiscount(IBRERuleContext aBRC, IDictionary aMap, object aStep) 57 { 58 Order _order = (Order)aBRC.GetObject(ORDER); 59 double _d = Convert.ToDouble(Reflection.CastValue(aMap[PERCENT], typeof(double))); 60 return _order.TotalCost * _d; 61 } 62 private void btnDiscount_Click(object sender, EventArgs e) 63 { 64 try 65 { 66 //载入规则 67 IRulesDriver rulesDriver = new XBusinessRulesFileDriver(FLOW_RULES_FILENAME); 68 //工厂 69 BREFactory breFactory = new BREFactory(); 70 //引挚实例 71 IFlowEngine bre = breFactory.NewBRE(rulesDriver); 72 //委托实例 73 ExecuteRuleDelegate executeRuleDelegate = new ExecuteRuleDelegate(AppliedDiscount); 74 bre.RuleContext.SetFactory(APPLIED_DISCOUNT, new BRERuleFactory(executeRuleDelegate)); 75 //设置规则引挚环境变量 76 //Order order = new Order(5, 25, "A"); 77 Order order = new Order(Int32.Parse(this.txtQuantity.Text), Double.Parse(this.txtTotalCost.Text), this.txtClientRating.Text); 78 bre.RuleContext.SetObject(ORDER, order); 79 //执行 80 bre.Process(); 81 //得到执行结果 82 double result = (double)bre.RuleContext.GetResult(APPLIED_DISCOUNT).Result; 83 84 this.txtPayCost.Text = result.ToString(); 85 this.txtPayCost.ReadOnly = true; 86 //Console.Out.WriteLine("\nOrder: Calculated discounted total={0} (expected: {1})\n", 87 // result, 25); 88 //Console.ReadLine(); 89 } 90 catch (Exception ex) 91 { 92 MessageBox.Show(ex.Message); 93 } 94 } 95 96 private void frmDiscountRBE_Load(object sender, EventArgs e) 97 { 98 99 } 100 101 } 102 }
运行程序,界面如下:
数量>40,折扣0.7 | 数量大于10且小于40,折扣0.8 |