|
1 | 1 | MicroRuleEngine is a single file rule engine |
2 | 2 | ============================================ |
3 | 3 |
|
4 | | -A .Net Rule Engine for dynamically evaluating business rules compiled on the fly. If you have business rules that you don't want to hard code then |
5 | | -the MicroRuleEngine is your friend. The rule engine is easy to groc and is only about 2 hundred lines. Under the covers it creates a Linq expression tree |
6 | | -that is compiled so even if your business rules get pretty large or you run them against thousands of items the performance should still compare nicely with a |
7 | | -hard coded solution. |
| 4 | +A `.Net` Rule Engine for **dynamically** evaluating business rules compiled on the fly. If you have business rules that you don't want to hard code then the `MicroRuleEngine` is your friend. The rule engine is easy to groc and is only about 200 lines of code. Under the covers it creates a `Linq` expression tree that is compiled so even if your business rules get pretty large or you run them against thousands of items the performance should still compare nicely with a hard coded solution. |
8 | 5 |
|
9 | 6 | How To Install It? |
10 | 7 | ------------------ |
11 | 8 | Drop the code file into your app and change it as you wish. |
12 | 9 |
|
13 | 10 | How Do You Use It? |
14 | 11 | ------------------ |
15 | | -The best examples of how to use the MicroRuleEngine (MRE) can be found in the Test project included in the Solution. |
16 | | -Below is one of the tests. |
| 12 | +The best examples of how to use the `MicroRuleEngine (MRE)` can be found in the Test project included in the Solution. |
17 | 13 |
|
| 14 | +One of the tests: |
18 | 15 | ```csharp |
19 | | - [TestMethod] |
20 | | - public void ChildProperties() |
| 16 | + [TestMethod] |
| 17 | + public void ChildProperties() |
| 18 | + { |
| 19 | + Order order = this.GetOrder(); |
| 20 | + Rule rule = new Rule() |
21 | 21 | { |
22 | | - Order order = this.GetOrder(); |
23 | | - Rule rule = new Rule() |
24 | | - { |
25 | | - MemberName = "Customer.Country.CountryCode", |
26 | | - Operator = System.Linq.Expressions.ExpressionType.Equal.ToString("g"), |
27 | | - TargetValue = "AUS" |
28 | | - }; |
29 | | - MRE engine = new MRE(); |
30 | | - var compiledRule = engine.CompileRule<Order>(rule); |
31 | | - bool passes = compiledRule(order); |
32 | | - Assert.IsTrue(passes); |
33 | | - |
34 | | - order.Customer.Country.CountryCode = "USA"; |
35 | | - passes = compiledRule(order); |
36 | | - Assert.IsFalse(passes); |
37 | | - } |
| 22 | + MemberName = "Customer.Country.CountryCode", |
| 23 | + Operator = System.Linq.Expressions.ExpressionType.Equal.ToString("g"), |
| 24 | + TargetValue = "AUS" |
| 25 | + }; |
| 26 | + MRE engine = new MRE(); |
| 27 | + var compiledRule = engine.CompileRule<Order>(rule); |
| 28 | + bool passes = compiledRule(order); |
| 29 | + Assert.IsTrue(passes); |
| 30 | + |
| 31 | + order.Customer.Country.CountryCode = "USA"; |
| 32 | + passes = compiledRule(order); |
| 33 | + Assert.IsFalse(passes); |
| 34 | + } |
38 | 35 | ``` |
39 | 36 |
|
40 | 37 | What Kinds of Rules can I express |
41 | 38 | -------------------------------- |
42 | | -In addition to comparative operators such as Equals, GreaterThan, LessThan etc. You can also call methods on the object that return a boolean value |
43 | | -such as Contains or StartsWith On a string. In addition to comparative operators additional operators such as "IsMatch" or "IsInteger" have been added |
44 | | -and demonstrates how you could edit the code and add your own operator. Rules can also be ANDed or ORed together as shown below. |
45 | | - |
| 39 | +In addition to comparative operators such as `Equals`, `GreaterThan`, `LessThan` etc. You can also call methods on the object that return a `boolean` value such as `Contains` or `StartsWith` on a string. In addition to comparative operators, additional operators such as `IsMatch` or `IsInteger` have been added and demonstrates how you could edit the code to add your own operator(s). Rules can also be `AND`'d or `OR`'d together: |
46 | 40 | ```csharp |
47 | 41 |
|
48 | | -Rule rule = Rule.Create("Customer.LastName", "Contains", "Do") |
49 | | - & (Rule.Create("Customer.FirstName", "StartsWith", "Jo")); |
50 | | - |
| 42 | + Rule rule = |
| 43 | + Rule.Create("Customer.LastName", "Contains", "Do") |
| 44 | + & ( |
| 45 | + Rule.Create("Customer.FirstName", "StartsWith", "Jo") |
| 46 | + | Rule.Create("Customer.FirstName", "StartsWith", "Bob") |
| 47 | + ); |
51 | 48 | ``` |
52 | 49 |
|
53 | | -You can reference member properties which are Arrays or List<> by their index |
| 50 | +You can reference member properties which are `Arrays` or `List<>` by their index: |
54 | 51 | ```csharp |
55 | | -Rule rule = Rule.Create("Items[1].Cost", mreOperator.GreaterThanOrEqual, "5.25"); |
| 52 | + Rule rule = Rule.Create("Items[1].Cost", mreOperator.GreaterThanOrEqual, "5.25"); |
56 | 53 | ``` |
57 | 54 |
|
58 | | -You can also compare an object to itself indicated by the "*." at the beginning of the TargetValue shown below |
| 55 | +You can also compare an object to itself indicated by the `*.` at the beginning of the `TargetValue`: |
59 | 56 | ```csharp |
60 | | -Rule rule = Rule.Create("Items[1].Cost", mreOperator.Equal, "*.Items[0].Cost"); |
| 57 | + Rule rule = Rule.Create("Items[1].Cost", mreOperator.Equal, "*.Items[0].Cost"); |
61 | 58 | ``` |
62 | 59 |
|
63 | | -There are a lot of examples in the Test cases but here is another snippet demonstrating nested OR logic |
64 | | - |
| 60 | +There are a lot of examples in the test cases but, here is another snippet demonstrating nested `OR` logic: |
65 | 61 | ```csharp |
66 | | - [TestMethod] |
67 | | - public void ConditionalLogic() |
| 62 | + [TestMethod] |
| 63 | + public void ConditionalLogic() |
| 64 | + { |
| 65 | + Order order = this.GetOrder(); |
| 66 | + Rule rule = new Rule() |
68 | 67 | { |
69 | | - Order order = this.GetOrder(); |
70 | | - Rule rule = new Rule() |
| 68 | + Operator = "AndAlso", |
| 69 | + Rules = new List<Rule>() |
71 | 70 | { |
72 | | - Operator = "AndAlso", |
73 | | - Rules = new List<Rule>() |
74 | | - { |
75 | | - new Rule(){ MemberName = "Customer.LastName", TargetValue = "Doe", Operator = "Equal"}, |
76 | | - new Rule(){ |
77 | | - Operator = "Or", |
78 | | - Rules = new List<Rule>(){ |
79 | | - new Rule(){ MemberName = "Customer.FirstName", TargetValue = "John", Operator = "Equal"}, |
80 | | - new Rule(){ MemberName = "Customer.FirstName", TargetValue = "Jane", Operator = "Equal"} |
81 | | - } |
| 71 | + new Rule() { MemberName = "Customer.LastName", TargetValue = "Doe", Operator = "Equal"}, |
| 72 | + new Rule() { |
| 73 | + Operator = "Or", |
| 74 | + Rules = new List<Rule>() { |
| 75 | + new Rule(){ MemberName = "Customer.FirstName", TargetValue = "John", Operator = "Equal"}, |
| 76 | + new Rule(){ MemberName = "Customer.FirstName", TargetValue = "Judy", Operator = "Equal"} |
82 | 77 | } |
83 | 78 | } |
84 | | - }; |
85 | | - MRE engine = new MRE(); |
86 | | - var fakeName = engine.CompileRule<Order>(rule); |
87 | | - bool passes = fakeName(order); |
88 | | - Assert.IsTrue(passes); |
| 79 | + } |
| 80 | + }; |
| 81 | + MRE engine = new MRE(); |
| 82 | + var fakeName = engine.CompileRule<Order>(rule); |
| 83 | + bool passes = fakeName(order); |
| 84 | + Assert.IsTrue(passes); |
| 85 | + |
| 86 | + order.Customer.FirstName = "Philip"; |
| 87 | + passes = fakeName(order); |
| 88 | + Assert.IsFalse(passes); |
| 89 | + } |
89 | 90 |
|
90 | | - order.Customer.FirstName = "Philip"; |
91 | | - passes = fakeName(order); |
92 | | - Assert.IsFalse(passes); |
93 | | - } |
94 | 91 | ``` |
95 | 92 |
|
96 | | -If you need to run your comparison against an ADO.NET DataSet you can also do that as well. |
97 | | - |
| 93 | +If you need to run your comparison against an ADO.NET DataSet you can also do that as well: |
98 | 94 | ```csharp |
99 | | -Rule rule = Rule.Create("Items[1].Cost", mreOperator.Equal, "*.Items[0].Cost"); |
| 95 | + Rule rule = Rule.Create("Items[1].Cost", mreOperator.Equal, "*.Items[0].Cost"); |
100 | 96 | ``` |
101 | 97 |
|
102 | | -How do I store Rules? |
| 98 | +How Can I Store Rules? |
103 | 99 | --------------------- |
104 | | -The Rule Class is just a POCO so you can store your rules as serialized XML, JSON etc. |
| 100 | +The `Rule` Class is just a **POCO** so you can store your rules as serialized `XML`, `JSON`, etc. |
105 | 101 |
|
106 | 102 | #### Forked many times and now updated to pull in a lot of the great work done by jamescurran, nazimkov and others that help improve the API |
107 | | - |
0 commit comments