Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Users/abbasc52/doc updates #555

Merged
merged 3 commits into from
Nov 26, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 84 additions & 3 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ RulesEngine is a highly extensible library to build rule based system using C# e
- Extending expression via custom class/type injection
- Scoped parameters
- Post rule execution actions
- Standalone expression evaluator

**Table Of Content**
- [Installation](#installation)
Expand All @@ -18,11 +19,13 @@ RulesEngine is a highly extensible library to build rule based system using C# e
- [Execute the workflow rules with input:](#execute-the-workflow-rules-with-input)
- [Using custom names for inputs](#using-custom-names-for-inputs)
- [C# Expression support](#c-expression-support)
- [Extending expression via custom class/type injection](#extending-expression-via-custom-classtype-injection)
- [Example](#example)
- [ScopedParams](#scopedparams)
- [GlobalParams](#globalparams)
- [Example](#example)
- [LocalParams](#localparams)
- [Example](#example-1)
- [LocalParams](#localparams)
- [Example](#example-2)
- [Referencing ScopedParams in other ScopedParams](#referencing-scopedparams-in-other-scopedparams)
- [Post rule execution actions](#post-rule-execution-actions)
- [Inbuilt Actions](#inbuilt-actions)
Expand All @@ -32,6 +35,8 @@ RulesEngine is a highly extensible library to build rule based system using C# e
- [Usage](#usage-1)
- [Custom Actions](#custom-actions)
- [Steps to use a custom Action](#steps-to-use-a-custom-action)
- [Standalone Expression Evaluator](#standalone-expression-evaluator)
- [Usage](#usage-2)



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


## Extending expression via custom class/type injection
Although RulesEngine supports C# expressions, you may need to perform more complex operation.

RulesEngine supports injecting custom classes/types via `ReSettings` which can allow you to call properties and methods of your custom class in expressions

### Example
Create a custom static class
```c#
using System;
using System.Linq;

namespace RE.HelperFunctions
{
public static class Utils
{
public static bool CheckContains(string check, string valList)
{
if (String.IsNullOrEmpty(check) || String.IsNullOrEmpty(valList))
return false;

var list = valList.Split(',').ToList();
return list.Contains(check);
}
}
}
```

Add it in your ReSettings and pass in RulesEngine constructor

```c#
var reSettings = new ReSettings{
CustomTypes = new Type[] { typeof(Utils) }
}

var rulesEngine = new RulesEngine.RulesEngine(workflowRules,reSettings);
```

With this you can call Utils class in your Rules

```json
{
"WorkflowName": "DiscountWithCustomInputNames",
"Rules": [
{
"RuleName": "GiveDiscount10",
"Expression": "Utils.CheckContains(input1.country, \"india,usa,canada,France\") == true"
}
abbasc52 marked this conversation as resolved.
Show resolved Hide resolved
}

```


## ScopedParams
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.

Expand Down Expand Up @@ -471,5 +528,29 @@ Actions can have async code as well
}
```

## Standalone Expression Evaluator
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.

### Usage
```c#
using System;
using RulesEngine.Models;
using RulesEngine.ExpressionBuilders;

public class Program
{
public static void Main()
{
var reParser = new RuleExpressionParser(new ReSettings());
var result = reParser.Evaluate<string>("a+b", new RuleParameter[]{
new RuleParameter("a","Hello "),
new RuleParameter("b","World")
});
Console.WriteLine(result);
}
}
```
This will output "Hello World"

For more advanced usage, refer - https://dotnetfiddle.net/KSX8i0

_For more details please check out [Rules Engine Wiki](https://github.com/microsoft/RulesEngine/wiki)._
4 changes: 2 additions & 2 deletions src/RulesEngine/ExpressionBuilders/RuleExpressionParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ public class RuleExpressionParser
private readonly ReSettings _reSettings;
private readonly IDictionary<string, MethodInfo> _methodInfo;

public RuleExpressionParser(ReSettings reSettings)
public RuleExpressionParser(ReSettings reSettings = null)
{
_reSettings = reSettings;
_reSettings = reSettings ?? new ReSettings();
_methodInfo = new Dictionary<string, MethodInfo>();
PopulateMethodInfo();
}
Expand Down
22 changes: 11 additions & 11 deletions test/RulesEngine.UnitTest/TypedClassTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,11 @@ public async Task TypedClassInputSameNameAsTypeTest()
var re = new RulesEngine(reSettings);
re.AddWorkflow(workflow);

var param = new Transazione {
var param = new Transazione {
Attori = new List<Attore>{
new Attore{
RuoloAttore = RuoloAttore.B,
RuoloAttore = RuoloAttore.B,

},
new Attore {
RuoloAttore = RuoloAttore.C
Expand All @@ -137,9 +137,9 @@ public async Task TypedClassInputSameNameAsTypeTest()

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

}
}


[Fact]
public async Task TypedClassBothAccessibleTestWhenCaseInsensitive()
{
Expand All @@ -163,8 +163,8 @@ public async Task TypedClassBothAccessibleTestWhenCaseInsensitive()
Expression = "transazione.Attori != null",
},
new() {
RuleName = "Static FieldTest",
Expression = "Transazione.StaticProperty == \"Hello\""
RuleName = "Static FieldTest",
Expression = "Transazione.StaticProperty == \"Hello\""
}
}
};
Expand All @@ -177,11 +177,11 @@ public async Task TypedClassBothAccessibleTestWhenCaseInsensitive()
var re = new RulesEngine(reSettings);
re.AddWorkflow(workflow);

var param = new Transazione {
var param = new Transazione {
Attori = new List<Attore>{
new Attore{
RuoloAttore = RuoloAttore.B,
RuoloAttore = RuoloAttore.B,

},
new Attore {
RuoloAttore = RuoloAttore.C
Expand Down