規則引擎由推理引擎發展而來,是一種嵌入在應用程式中的組件,實現了將業務決策從應用程式代碼中分離出來,並使用預定義的語義模塊編寫業務決策。接受數據輸入,解釋業務規則,並根據業務規則做出業務決策。比較常見的業務規則引擎有Drools、VisualRules 和iLog。這裡介紹另外一個C#開源工具Rul
規則引擎由推理引擎發展而來,是一種嵌入在應用程式中的組件,實現了將業務決策從應用程式代碼中分離出來,並使用預定義的語義模塊編寫業務決策。接受數據輸入,解釋業務規則,並根據業務規則做出業務決策。比較常見的業務規則引擎有Drools、VisualRules 和iLog。這裡介紹另外一個C#開源工具RulesEngine。下麵通過一個例子來他如何使用。
1 項目結構
在RulesEngine源代碼中添加一個RulesEngineDemo的窗體應用程式,然後引用需要的類庫,如下圖所示:
2 訂單等實體類定義
這裡用訂單的場景來用規則引擎處理折扣的業務邏輯:
public class Order { public double amount; public double num; public double discount; public double afteramount; public DateTime datetime; public List<items> ItemLists; public string maker;//購買人 public string wfprocess;//審批人 public string wfprocessname;//審批人 public string memo;//備註 public override string ToString() { string res = string.Format("折扣={0},金額={1},審批人={2}({4}),折後金額={3}", discount, amount, wfprocess, afteramount,wfprocessname); return res; } } //用戶 public class Emp { public string id; public string leader; public string name; } //明細 public class items { public string productid; public string productname; public double price; public double num; public double discount; public double amount; public double afteramount; }
3 窗體定義
下麵我們創建一個訂單明細的窗體,用來修改金額等數據,用來測試業務規則是否正常運行:、
1 public partial class FrmOrder : Form 2 { 3 public FrmOrder() 4 { 5 InitializeComponent(); 6 dgvOrder = this.dataGridView1; 7 } 8 9 public DataGridView dgvOrder; 10 private void FrmOrder_Load(object sender, EventArgs e) 11 { 12 this.dataGridView1.Rows.Add(new object[] { "1", "p1", "20", "10", "200", "1","200","01.01" }); 13 this.dataGridView1.Rows.Add(new object[] { "2", "p2", "1", "8", "8", "1", "8", "01.01" }); 14 15 } 16 17 private void 保存SToolStripButton_Click(object sender, EventArgs e) 18 { 19 this.Hide(); 20 } 21 }
然後我們定義一個主界面來定義規則和調用處理邏輯:
1 using RulesEngine; 2 using RulesEngine.BooEvaluator; 3 public partial class Form1 : Form 4 { 5 6 DataGridView dgvOrder = null; 7 public Form1() 8 { 9 InitializeComponent(); 10 } 11 12 private void Form1_Load(object sender, EventArgs e) 13 { 14 this.dataGridView1.Rows.Add(new object[] {"return (訂單.金額>200)",@" 15 訂單.折扣=0.9; 16 訂單.審批人=""admin""; 17 訂單.折後金額=訂單.金額*訂單.折扣; 18 訂單.備註 = ""規則引擎產生""; 19 return true;" }); 20 this.dataGridView1.Rows.Add(new object[] {"return (訂單.金額<=200 且 訂單.金額>100)",@" 21 訂單.折扣=0.8; 22 訂單.折後金額=訂單.金額*訂單.折扣; 23 訂單.備註 = ""規則引擎產生""; 24 return true;" }); 25 26 this.dataGridView1.Rows.Add(new object[] {"return (訂單.金額<=100 且 訂單.金額>0)",@" 27 訂單.折扣=1.0; 28 訂單.折後金額=訂單.金額*訂單.折扣; 29 訂單.備註 = ""規則引擎產生""; 30 return true;" }); 31 32 } 33 //run 34 private void 保存SToolStripButton_Click(object sender, EventArgs e) 35 { 36 37 38 DslRuleTests test = new DslRuleTests(); 39 test.Setup(); 40 41 //test.EvaluateRules(); 42 43 var order = test.EvaluateRules(this.dataGridView1, dgvOrder); 44 this.txtResults.Text = order.ToString(); 45 46 47 48 } 49 50 private void toolStripButton1_Click(object sender, EventArgs e) 51 { 52 FrmOrder frm = new FrmOrder(); 53 54 frm.ShowDialog(); 55 56 dgvOrder = frm.dgvOrder; 57 } 58 } 59 60 public class DslRuleTests 61 { 62 private BooLangEvaluator evaluator; 63 64 private List<Emp> listEmp = new List<Emp>(); 65 66 public void Setup() 67 { 68 var dslEngineStorage = new DslEngineStorage(); 69 70 evaluator = new BooLangEvaluator(dslEngineStorage); 71 72 listEmp.Add(new Emp { id = "01", leader ="00" ,name="jack"}); 73 listEmp.Add(new Emp { id = "01.01", leader = "01", name = "smith" }); 74 listEmp.Add(new Emp { id = "01.01.01", leader = "01.01", name = "john" }); 75 76 77 } 78 //審批處理 79 private void SP(Order o) 80 { 81 82 foreach (Emp emp in listEmp) 83 { 84 if (emp.id == o.maker) 85 { 86 o.wfprocess = emp.leader; 87 o.wfprocessname = getName(o.wfprocess); 88 } 89 } 90 91 92 } 93 //獲取職工姓名 94 private string getName(string id) 95 { 96 foreach (Emp emp in listEmp) 97 { 98 if (emp.id == id) 99 { 100 101 return emp.name; 102 } 103 } 104 return ""; 105 } 106 //求和 107 private void SumAmount(Order o) 108 { 109 var sum = o.ItemLists.AsQueryable().Sum(x => x.amount); 110 o.amount = sum; 111 } 112 //解析規則腳本 113 public Order EvaluateRules(DataGridView dgv,DataGridView dgvOrder) 114 { 115 Order order =new Order { memo = "", maker = "01.01", discount = 1, datetime = DateTime.Now }; 116 order.ItemLists = new List<items>(); 117 foreach (DataGridViewRow dr in dgvOrder.Rows) 118 { 119 if (dr.Cells[0].Value != null) 120 { 121 var item = new items 122 { 123 productid = dr.Cells[0].Value.ToString(), 124 productname = dr.Cells[1].Value.ToString(), 125 price = double.Parse(dr.Cells[2].Value.ToString()), 126 num = double.Parse(dr.Cells[3].Value.ToString()), 127 amount = double.Parse(dr.Cells[4].Value.ToString()), 128 discount = double.Parse(dr.Cells[5].Value.ToString()), 129 afteramount = double.Parse(dr.Cells[6].Value.ToString()) 130 131 }; 132 133 order.ItemLists.Add(item); 134 } 135 } 136 137 SumAmount(order); 138 SP(order); 139 string strDslStatement=""; 140 string strDslActivity = ""; 141 EvaluatorAccessPoint.DslConditionEvaluator = evaluator; 142 143 foreach (DataGridViewRow dr in dgv.Rows) 144 { 145 146 strDslStatement = dr.Cells[0].Value.ToString() 147 .Replace("訂單", "this") 148 .Replace("金額", "amount") 149 .Replace("且", "and") 150 .Replace("或", "or"); 151 strDslActivity = dr.Cells[1].Value.ToString() 152 .Replace("折扣", "discount") 153 .Replace("折後金額", "afteramount") 154 .Replace("金額", "amount") 155 .Replace("訂單", "this") 156 .Replace("備註", "memo") 157 .Replace("審批人", "wfprocessname") 158 .Replace("且", "and") 159 .Replace("或", "or"); 160 161 var conditionRule = new DslCondition { DslStatement = strDslStatement }; 162 163 var rule = new ActivityRule(conditionRule, new DslActivity 164 { 165 DslStatement = strDslActivity 166 }); 167 168 var result = rule.Evaluate(order); 169 if (result) 170 { 171 //break; 172 return order; 173 174 } 175 176 177 } 178 return null; 179 180 } 181 182 }View Code
4 結果展示
運行代碼,界面如下: