Skip to content

Commit 9bcf4f3

Browse files
authored
Users/abbasc52/doc updates (#555)
* added custom type injection in docs * updated expression parser to support null Resettings and added standalone evaluator sample * fixed missing bracket
1 parent b783602 commit 9bcf4f3

3 files changed

Lines changed: 98 additions & 16 deletions

File tree

docs/index.md

Lines changed: 85 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ RulesEngine is a highly extensible library to build rule based system using C# e
99
- Extending expression via custom class/type injection
1010
- Scoped parameters
1111
- Post rule execution actions
12+
- Standalone expression evaluator
1213

1314
**Table Of Content**
1415
- [Installation](#installation)
@@ -18,11 +19,13 @@ RulesEngine is a highly extensible library to build rule based system using C# e
1819
- [Execute the workflow rules with input:](#execute-the-workflow-rules-with-input)
1920
- [Using custom names for inputs](#using-custom-names-for-inputs)
2021
- [C# Expression support](#c-expression-support)
22+
- [Extending expression via custom class/type injection](#extending-expression-via-custom-classtype-injection)
23+
- [Example](#example)
2124
- [ScopedParams](#scopedparams)
2225
- [GlobalParams](#globalparams)
23-
- [Example](#example)
24-
- [LocalParams](#localparams)
2526
- [Example](#example-1)
27+
- [LocalParams](#localparams)
28+
- [Example](#example-2)
2629
- [Referencing ScopedParams in other ScopedParams](#referencing-scopedparams-in-other-scopedparams)
2730
- [Post rule execution actions](#post-rule-execution-actions)
2831
- [Inbuilt Actions](#inbuilt-actions)
@@ -32,6 +35,8 @@ RulesEngine is a highly extensible library to build rule based system using C# e
3235
- [Usage](#usage-1)
3336
- [Custom Actions](#custom-actions)
3437
- [Steps to use a custom Action](#steps-to-use-a-custom-action)
38+
- [Standalone Expression Evaluator](#standalone-expression-evaluator)
39+
- [Usage](#usage-2)
3540

3641

3742

@@ -123,6 +128,59 @@ For more details on supported expression language refer - [expression language](
123128
For supported linq operations refer - [sequence operators](https://dynamic-linq.net/expression-language#sequence-operators)
124129

125130

131+
## Extending expression via custom class/type injection
132+
Although RulesEngine supports C# expressions, you may need to perform more complex operation.
133+
134+
RulesEngine supports injecting custom classes/types via `ReSettings` which can allow you to call properties and methods of your custom class in expressions
135+
136+
### Example
137+
Create a custom static class
138+
```c#
139+
using System;
140+
using System.Linq;
141+
142+
namespace RE.HelperFunctions
143+
{
144+
public static class Utils
145+
{
146+
public static bool CheckContains(string check, string valList)
147+
{
148+
if (String.IsNullOrEmpty(check) || String.IsNullOrEmpty(valList))
149+
return false;
150+
151+
var list = valList.Split(',').ToList();
152+
return list.Contains(check);
153+
}
154+
}
155+
}
156+
```
157+
158+
Add it in your ReSettings and pass in RulesEngine constructor
159+
160+
```c#
161+
var reSettings = new ReSettings{
162+
CustomTypes = new Type[] { typeof(Utils) }
163+
}
164+
165+
var rulesEngine = new RulesEngine.RulesEngine(workflowRules,reSettings);
166+
```
167+
168+
With this you can call Utils class in your Rules
169+
170+
```json
171+
{
172+
"WorkflowName": "DiscountWithCustomInputNames",
173+
"Rules": [
174+
{
175+
"RuleName": "GiveDiscount10",
176+
"Expression": "Utils.CheckContains(input1.country, \"india,usa,canada,France\") == true"
177+
}
178+
]
179+
}
180+
181+
```
182+
183+
126184
## ScopedParams
127185
Sometimes Rules can get very long and complex, scopedParams allow users to replace an expression in rule with an alias making it easier to maintain rule.
128186

@@ -471,5 +529,29 @@ Actions can have async code as well
471529
}
472530
```
473531

532+
## Standalone Expression Evaluator
533+
If you are not looking for a full fledged RulesEngine and need only an expression evaluator. RulesEngine offers `RuleExpressionParser` which handles expression parsing and evaluation.
534+
535+
### Usage
536+
```c#
537+
using System;
538+
using RulesEngine.Models;
539+
using RulesEngine.ExpressionBuilders;
540+
541+
public class Program
542+
{
543+
public static void Main()
544+
{
545+
var reParser = new RuleExpressionParser(new ReSettings());
546+
var result = reParser.Evaluate<string>("a+b", new RuleParameter[]{
547+
new RuleParameter("a","Hello "),
548+
new RuleParameter("b","World")
549+
});
550+
Console.WriteLine(result);
551+
}
552+
}
553+
```
554+
This will output "Hello World"
555+
556+
For more advanced usage, refer - https://dotnetfiddle.net/KSX8i0
474557
475-
_For more details please check out [Rules Engine Wiki](https://github.com/microsoft/RulesEngine/wiki)._

src/RulesEngine/ExpressionBuilders/RuleExpressionParser.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ public class RuleExpressionParser
1919
private readonly ReSettings _reSettings;
2020
private readonly IDictionary<string, MethodInfo> _methodInfo;
2121

22-
public RuleExpressionParser(ReSettings reSettings)
22+
public RuleExpressionParser(ReSettings reSettings = null)
2323
{
24-
_reSettings = reSettings;
24+
_reSettings = reSettings ?? new ReSettings();
2525
_methodInfo = new Dictionary<string, MethodInfo>();
2626
PopulateMethodInfo();
2727
}

test/RulesEngine.UnitTest/TypedClassTests.cs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,11 @@ public async Task TypedClassInputSameNameAsTypeTest()
120120
var re = new RulesEngine(reSettings);
121121
re.AddWorkflow(workflow);
122122

123-
var param = new Transazione {
123+
var param = new Transazione {
124124
Attori = new List<Attore>{
125125
new Attore{
126-
RuoloAttore = RuoloAttore.B,
127-
126+
RuoloAttore = RuoloAttore.B,
127+
128128
},
129129
new Attore {
130130
RuoloAttore = RuoloAttore.C
@@ -137,9 +137,9 @@ public async Task TypedClassInputSameNameAsTypeTest()
137137

138138
Assert.All(result, (res) => Assert.True(res.IsSuccess));
139139

140-
}
141-
142-
140+
}
141+
142+
143143
[Fact]
144144
public async Task TypedClassBothAccessibleTestWhenCaseInsensitive()
145145
{
@@ -163,8 +163,8 @@ public async Task TypedClassBothAccessibleTestWhenCaseInsensitive()
163163
Expression = "transazione.Attori != null",
164164
},
165165
new() {
166-
RuleName = "Static FieldTest",
167-
Expression = "Transazione.StaticProperty == \"Hello\""
166+
RuleName = "Static FieldTest",
167+
Expression = "Transazione.StaticProperty == \"Hello\""
168168
}
169169
}
170170
};
@@ -177,11 +177,11 @@ public async Task TypedClassBothAccessibleTestWhenCaseInsensitive()
177177
var re = new RulesEngine(reSettings);
178178
re.AddWorkflow(workflow);
179179

180-
var param = new Transazione {
180+
var param = new Transazione {
181181
Attori = new List<Attore>{
182182
new Attore{
183-
RuoloAttore = RuoloAttore.B,
184-
183+
RuoloAttore = RuoloAttore.B,
184+
185185
},
186186
new Attore {
187187
RuoloAttore = RuoloAttore.C

0 commit comments

Comments
 (0)