基於RulesEngine的業務規則實現


  規則引擎由推理引擎發展而來,是一種嵌入在應用程序中的組件,實現了將業務決策從應用程序代碼中分離出來,並使用預定義的語義模塊編寫業務決策。接受數據輸入,解釋業務規則,並根據業務規則做出業務決策。比較常見的業務規則引擎有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 結果展示

運行代碼,界面如下:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM