Fork me on GitHub

基于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 结果展示

运行代码,界面如下:

posted @ 2016-03-11 10:51  JackWang-CUMT  阅读(5582)  评论(1编辑  收藏  举报