Abbasc52/docs checkin (#104)

* moved wiki docs to repo
pull/107/head
Abbas Cyclewala 2021-02-10 14:34:28 +05:30 committed by GitHub
parent 470fc76216
commit 2dbdcdd7c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 520 additions and 0 deletions

239
docs/Getting-Started.md Normal file
View File

@ -0,0 +1,239 @@
## Getting Started with Rules Engine
RulesEngine is a library/NuGet package for abstracting rules and running the Rules Engine.
### Publicly accessible interfaces, models, methods and schemas
As with any library/package there are public interfaces with which we interact with that library/packages. There are a few public interfaces in this package as well. The interface which will be used to access this package is [IRulesEngine](#irulesengine), with four overloaded methods for executing rules. To understand the methods, we need to go through some of the models/schemas first.
#### Rules
The rules used in this system is mostly comprising of [lambda expressions](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/lambda-expressions). Anything that can be defined in a lambda expression can be used as a rule in this library.
#### Rules Schema
Rules schema is available in the [schema file](https://github.com/microsoft/RulesEngine/blob/master/schema/workflowRules-schema.json). The workflow rules are how we store the rules in the system. In our system, the name of the model typed in the library is [WorkflowRules](https://github.com/microsoft/RulesEngine/blob/master/src/RulesEngine/RulesEngine/Models/WorkflowRules.cs). An example json would be
```json
[
{
"WorkflowName": "Discount",
"Rules": [
{
"RuleName": "GiveDiscount10",
"SuccessEvent": "10",
"ErrorMessage": "One or more adjust rules failed.",
"ErrorType": "Error",
"RuleExpressionType": "LambdaExpression",
"Expression": "input1.country == \"india\" AND input1.loyalityFactor <= 2 AND input1.totalPurchasesToDate >= 5000 AND input2.totalOrders > 2 AND input3.noOfVisitsPerMonth > 2"
},
{
"RuleName": "GiveDiscount20",
"SuccessEvent": "20",
"ErrorMessage": "One or more adjust rules failed.",
"ErrorType": "Error",
"RuleExpressionType": "LambdaExpression",
"Expression": "input1.country == \"india\" AND input1.loyalityFactor == 3 AND input1.totalPurchasesToDate >= 10000 AND input2.totalOrders > 2 AND input3.noOfVisitsPerMonth > 2"
},
{
"RuleName": "GiveDiscount25",
"SuccessEvent": "25",
"ErrorMessage": "One or more adjust rules failed.",
"ErrorType": "Error",
"RuleExpressionType": "LambdaExpression",
"Expression": "input1.country != \"india\" AND input1.loyalityFactor >= 2 AND input1.totalPurchasesToDate >= 10000 AND input2.totalOrders > 2 AND input3.noOfVisitsPerMonth > 5"
},
{
"RuleName": "GiveDiscount30",
"SuccessEvent": "30",
"ErrorMessage": "One or more adjust rules failed.",
"ErrorType": "Error",
"RuleExpressionType": "LambdaExpression",
"Expression": "input1.loyalityFactor > 3 AND input1.totalPurchasesToDate >= 50000 AND input1.totalPurchasesToDate <= 100000 AND input2.totalOrders > 5 AND input3.noOfVisitsPerMonth > 15"
},
{
"RuleName": "GiveDiscount35",
"SuccessEvent": "35",
"ErrorMessage": "One or more adjust rules failed.",
"ErrorType": "Error",
"RuleExpressionType": "LambdaExpression",
"Expression": "input1.loyalityFactor > 3 AND input1.totalPurchasesToDate >= 100000 AND input2.totalOrders > 15 AND input3.noOfVisitsPerMonth > 25"
}
]
}
]
```
This workflow rules showcased in the above json is of a sample [Use Case](https://github.com/microsoft/RulesEngine/wiki/Use-Case) which is going to be used to explain the library.
Demo App for the given use case is available at [this location](https://github.com/microsoft/RulesEngine/tree/master/demo).
#### Logger
Another public interface for custom logging is ILogger. This interface is not implemented and looks for custom implementation of the user who wants to use it. The methods available for this interface are
```c#
void LogTrace(string msg);
void LogError(Exception ex);
```
These methods can be implemented in any logging mechanism that is expected and its instance can be injected into the Rules Engine as shown in [Initiating the Rules Engine](#initiating-the-rules-engine).
#### ReSettings
This model is a list of custom types.
While, lambda expressions are quite powerful, there is a limit to what they can do because of the fact that the methods that a lambda expression can do are limited to [System namespace](https://docs.microsoft.com/en-us/dotnet/api/system) of [.Net framework](https://docs.microsoft.com/en-us/dotnet/framework/).
To use more complex and custom classes and have some logics which are way too complex to be written into a lambda expression, these settings come into picture. If the user wants to create a custom method to run for the rule to be used, these settings help them.
Example
You can create a public class called Utils and include a method in it which check contains in a list.
```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);
}
}
}
```
And this can be then used in lambda expression in a very simple manner like this
```json
"Expression": "Utils.CheckContains(input1.country, \"india,usa,canada,France\") == true"
```
To use the custom class when evaluating the rules:
1. Register the class
2. Then pass settings through rules engine
```csharp
var reSettingsWithCustomTypes = new ReSettings { CustomTypes = new Type[] { typeof(Utils) } };
new RulesEngine.RulesEngine(workflowRules.ToArray(), null, reSettingsWithCustomTypes);
```
#### RuleParameter
This is a model class for custom inputs which can be seen in the [RuleParameter Class](https://github.com/microsoft/RulesEngine/blob/master/src/RulesEngine/RulesEngine/Models/RuleParameter.cs). This type is present to add another layer of customization to the rules.
For example, the rules present in the example mentioned in the [Rules Schema](#rules-schema) section are using 3 different inputs for each run. The inputs are of different types as mentioned in the [Use Case]((https://github.com/microsoft/RulesEngine/wiki/Use-Case)) and is coming from different sources. Now, in rules we had to use input1, input2 and input3 to target data coming from the basic info, order info and telemetry info, respectively.
With RuleParameter class, we can give context specific names to the rules in the list of rules instead of input1, input2 and input3.
#### LocalParams
Rules Engine has a param (like var in c#) feature support now, it makes authoring and troubleshooting of issues very easy. Now you can breakdown your bigger statements into smaller logical expressions as parameters within a rule definition.
Below is an example of a complex rule which can be authored easily using logical intermediate parameters and can be used to write the final rule expression to return a binary value. Sample rule requirement here is to provide access to a user only when user has completed some mandatory trainings or the user is accessing the site it from a secure domain.
```
{
"name": "allow_access_if_all_mandatory_trainings_are_done_or_access_isSecure",
"errorMessage": "Please complete all your training(s) to get access to this content or access it from a secure domain/location.",
"errorType": "Error",
"localParams": [
{
"name": "completedSecurityTrainings",
"expression": "MasterSecurityComplainceTrainings.Where(Status.Equals(\"Completed\", StringComparison.InvariantCultureIgnoreCase))"
},
{
"name": "completedProjectTrainings",
"expression": "MasterProjectComplainceTrainings.Where(Status.Equals(\"Completed\", StringComparison.InvariantCultureIgnoreCase))"
},
{
"name": "isRequestAccessSecured",
"expression": "UserRequestDetails.Location.Country == \"India\" ? ((UserRequestDetails.Location.City == \"Bangalore\" && UserRequestDetails.Domain=\"xxxx\")? true : false):false"
}
],
"expression": "(completedSecurityTrainings.Any() && completedProjectTrainings.Any()) || isRequestAccessSecured "
}
```
#### RuleResultTree
[This model](https://github.com/microsoft/RulesEngine/blob/master/src/RulesEngine/RulesEngine/Models/RuleResultTree.cs) is the output of the Rules Engine. Once the execution of the Rules Engine is completed and the Engine has gone through all the rules, a list of this type is returned. What this model include is
##### Rule
This is the rule that is currently being referred. It is of a custom model type and has information of that rule which ran on the input.
##### IsSuccess
This is a Boolean value showcasing whether the given rule passed or not.
##### ChildResults
In the case, the rule has child rules, this variable gets initialized else it is null. This is a nested list of RuleResultTree type to showcase the response of the children rules.
##### Input
This is the input that was being checked upon while the rules were being verified on this object. In case of multiple inputs, it takes up the first input.
#### IRulesEngine
IRulesEngine is the main interface which is used to handle all the executions. This interface has four overloaded methods to execute rules
```c#
List<RuleResultTree> ExecuteRule(string workflowName, IEnumerable<dynamic> input, object[] otherInputs);
List<RuleResultTree> ExecuteRule(string workflowName, object[] inputs);
List<RuleResultTree> ExecuteRule(string workflowName, object input);
List<RuleResultTree> ExecuteRule(string workflowName, RuleParameter[] ruleParams);
```
One Rules Engine can take in multiple workflows and the workflows can be distributed based on the logic dictated by the system you are building.
In the first definition
* workflowName is the name of the workflow you want to take up.
* input is a list of dynamic inputs which is being entered.
* otherInputs is an array of other auxiliary inputs which complement the inputs based on the rules present.
In the second definition
* workflowName is the name of the workflow you want to take up.
* input is an array of dynamic inputs which is being entered.
In the third definition
* workflowName is the name of the workflow you want to take up.
* input is a single dynamic input which is being entered.
In the fourth definition
* workflowName is the name of the workflow you want to take up.
* ruleParams is an array of RuleParameters as explained in [RuleParameter](#ruleparameter).
#### Initiating the Rules Engine
To initiate the Rules Engine instance to be used for executing rules, the workflow rules need to be injected into the library. The two different definitions of constructors are
```c#
public RulesEngine(string[] jsonConfig, ILogger logger, ReSettings reSettings = null)
public RulesEngine(WorkflowRules[] workflowRules, ILogger logger, ReSettings reSettings = null)
```
Here,
* jsonConfig is the list of serialized json strings following the schema mentioned in [Rules Schema](#rules-schema).
* logger is an instance of the logger created by you, following the information given in [Logger](#logger).
* reSettings is list of custom types as mention in [ReSettings](#resettings).
* workflowRules is a list of objects of type WorkflowRules which is mentioned in the [Rules Schema](#rules-schema).
#### Success/Failure
For the rules to make sense, there are always success and failure scenarios. This library gives the user an inbuilt scenario where in success and failure scenario an event can be created.
##### Success
In case of success, there could be one or more than one rules which passed based on the given input(s). The success event will be triggered and will be run based on the first rule which was true and give you the success event which was initialized as SuccessEvent in the RulesSchema section.
Example
```c#
List<RuleResultTree> resultList = bre.ExecuteRule("Discount", inputs);
resultList.OnSuccess((eventName) =>
{
discountOffered = $"Discount offered is {eventName} % over MRP.";
});
```
##### Failure
In case, none of the rules succeeded the failure event gets triggered.
Example
```c#
List<RuleResultTree> resultList = bre.ExecuteRule("Discount", inputs);
resultList.OnFail(() =>
{
discountOffered = "The user is not eligible for any discount.";
});
```
### How to use Rules Engine
1. To install this library, please download the latest version of [NuGet Package](https://www.nuget.org/packages/RulesEngine/) from [nuget.org](https://www.nuget.org/) and refer it into your project.
2. Initiate the instance of Rules Engine as mentioned in [Initiating the Rules Engine](#initiating-the-rules-engine).
3. Once done, the rules can be executed using any of the overloaded methods as explained in [IRulesEngine](#irulesengine) section. It returns the list of [RuleResultTree](#ruleresulttree) which can be used in any way the user wants to.
4. The success or failure events can be defined as explained in the [Success/Failure](#successfailure) section.
* Based on the rules and input the success or failure event can be triggered.

24
docs/Home.md Normal file
View File

@ -0,0 +1,24 @@
## Welcome
Welcome to the RulesEngine Wiki!
The pages here are primarily intended for those who wish to contribute to the Rules Engine Project by suggesting new features or building extensions or submitting pull requests.
This Wiki also includes a demo along with the explanation of different features of the project so that the using of the application can be easily understood.
## About
Deep dive into the project code and the Wiki to find different features and workings of the project.
Search for the solution or file a new issue in [GitHub](https://github.com/microsoft/RulesEngine/issues) if you find something broken in the code.
## Contributing
This project welcomes contributions and suggestions. Most contributions require you to agree to a
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
When you submit a pull request, a CLA bot will automatically determine whether you need to provide
a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.

22
docs/Introduction.md Normal file
View File

@ -0,0 +1,22 @@
## What is the Rules Engine
While building any application, the crux or the core part of it is always business logic or business rules. And as with any application, there always comes a time when some or a lot of the rules or policies change in the system. But with that change, comes a lot of rework like changing design or creating a new module altogether to code in the changes in the rules, regression testing, performance testing etc. The rework along with debugging if required amounts to a lot of unnecessary work which can otherwise be utilized for other work, thus reducing the engineering cycle by drastic amounts.
In this library, we have abstracted the rules so that the core logic is always maintained while the rules change can happen in an easy way without changing the code base. Also, the input to the system is dynamic in nature so the model need not be defined in the system. It can be sent as an expando object or any other typed object and the system will be able to handle it.
These all features make this library highly configurable and extensible as shown in [Getting Started with Rules Engine](https://github.com/microsoft/RulesEngine/wiki/Getting-Started).
### How it works
[[https://github.com/microsoft/RulesEngine/blob/master/assets/BlockDiagram.png|alt=octocat]]
Here. there are multiple actors/component involved.
##### Rules Engine
This component is the Rules Engine library/NuGet package being referenced by the developer.
##### Rules Store
As shown in [Rules Schema](https://github.com/microsoft/RulesEngine/wiki/Getting-Started#rules-schema), we need rules in a particular format for the library to work. While the rules structure is rigid, the data itself can be stored in any component and can be accessed in any form the developer chooses. It can be stored in the form of json files in file structure or blob, or as documents in cosmos db, or any database, azure app configuration or any other place the developer thinks is going to be appropriate based on the project requirements.
##### Input
The input(s) for the system can be taken from any place as well like user input, blobs, databases, service bus or any other system.
##### Wrapper
This library sits as a black box outside the project as a referenced project or NuGet package. Then the user can create a wrapper around the library, which will get the rules from the rules store and convert it into the WorkFlowRules structure and send it to the RulesEngine along with the input(s). The RulesEngine then computes and give the information to the wrapper and the wrapper can then do whatever the logic demands with the output information.

56
docs/Use-Case.md Normal file
View File

@ -0,0 +1,56 @@
## Use Case
The use case for demo purposes used here is explained as follows. The system we are designing is an e-commerce discount calculation system.
### Rules
The rules for the discount calculation are
1. Give the user a discount of 10% over MRP if the following conditions are followed
* The users country is India.
* The users loyalty factor is less than or equal to 2.
* All the orders purchased by the user so far should amount to more than 5,000.
* User should have at least made more than two successful orders.
* The user should have visited the site more than two times every month.
2. Give the user a discount of 20% over MRP if the following conditions are followed
* The users country is India.
* The users loyalty factor is equal to 3.
* All the orders purchased by the user so far should amount to more than 10,000.
* User should have at least made more than two successful orders.
* The user should have visited the site more than two times every month.
3. Give the user a discount of 25% over MRP if the following conditions are followed
* The users country is not India.
* The users loyalty factor is greater than or equal to 2.
* All the orders purchased by the user so far should amount to more than 10,000.
* User should have at least made more than two successful orders.
* The user should have visited the site more than five times every month.
4. Give the user a discount of 30% over MRP if the following conditions are followed
* The users loyalty factor is greater than 3.
* All the orders purchased by the user so far should amount to more than 50,000 but less than 100,000.
* User should have at least made more than five successful orders.
* The user should have visited the site more than fifteen times every month.
5. Give the user a discount of 30% over MRP if the following conditions are followed
* The users loyalty factor is greater than 3.
* All the orders purchased by the user so far should amount to more than 100,000.
* User should have at least made more than fifteen successful orders.
* The user should have visited the site more than 25 times every month.
6. Give 0% discount in any other case.
### Inputs
Here the inputs will be of three different types as they are coming from three different data sources/APIs.
#### User Basic Info
This input has information like
* Name
* Country
* Email
* Credit history
* Loyalty factor
* Sum of the purchases made by the user till date.
#### Users Order Information
This input is a summarization of the orders made by the user so far. This input has information like
* Total number of orders
* Recurring items in those orders if any
#### Users Telemetry Information
This input is a summarization of the telemetry information collected based on the users visit to the site. This input has information like
* Number of visits to the site per month
* Percentage of the number of times the user purchased something to the number of times the user visited

35
docs/_Sidebar.md Normal file
View File

@ -0,0 +1,35 @@
[Home](https://github.com/microsoft/RulesEngine/wiki)
* [Welcome](https://github.com/microsoft/RulesEngine/wiki#welcome)
* [About](https://github.com/microsoft/RulesEngine/wiki#about)
* [Contributing](https://github.com/microsoft/RulesEngine/wiki#contributing)
[Introduction](https://github.com/microsoft/RulesEngine/wiki/Introduction)
* [What is the Rules Engine](https://github.com/microsoft/RulesEngine/wiki/Introduction#what-is-the-rules-engine)
* [How it works](https://github.com/microsoft/RulesEngine/wiki/Introduction#how-it-works)
* [Rules Engine](https://github.com/microsoft/RulesEngine/wiki/Introduction#rules-engine)
* [Rules Store](https://github.com/microsoft/RulesEngine/wiki/Introduction#rules-store)
* [Input](https://github.com/microsoft/RulesEngine/wiki/Introduction#input)
* [Wrapper](https://github.com/microsoft/RulesEngine/wiki/Introduction#wrapper)
[Getting Started](https://github.com/microsoft/RulesEngine/wiki/Getting-Started)
* [Getting Started with Rules Engine](https://github.com/microsoft/RulesEngine/wiki/Getting-Started#getting-started-with-rules-engine)
* [Publicly accessible interfaces, models, methods and schemas](https://github.com/microsoft/RulesEngine/wiki/Getting-Started#publicly-accessible-interfaces-models-methods-and-schemas)
* [Rules](https://github.com/microsoft/RulesEngine/wiki/Getting-Started#rules)
* [Rules Schema](https://github.com/microsoft/RulesEngine/wiki/Getting-Started#rules-schema)
* [Logger](https://github.com/microsoft/RulesEngine/wiki/Getting-Started#logger)
* [ReSettings](https://github.com/microsoft/RulesEngine/wiki/Getting-Started#resettings)
* [LocalParams](https://github.com/microsoft/RulesEngine/wiki/Getting-Started#localparams)
* [RuleParameter](https://github.com/microsoft/RulesEngine/wiki/Getting-Started#ruleparameter)
* [RuleResultTree](https://github.com/microsoft/RulesEngine/wiki/Getting-Started#ruleresulttree)
* [IRulesEngine](https://github.com/microsoft/RulesEngine/wiki/Getting-Started#irulesengine)
* [Initiating the Rules Engine](https://github.com/microsoft/RulesEngine/wiki/Getting-Started#initiating-the-rules-engine)
* [Success/Failure](https://github.com/microsoft/RulesEngine/wiki/Getting-Started#successfailure)
* [How to use Rules Engine](https://github.com/microsoft/RulesEngine/wiki/Getting-Started#how-to-use-rules-engine)
[Use Case](https://github.com/microsoft/RulesEngine/wiki/Use-Case)
* [Use Case](https://github.com/microsoft/RulesEngine/wiki/Use-Case#use-case)
* [Rules](https://github.com/microsoft/RulesEngine/wiki/Use-Case#rules)
* [Inputs](https://github.com/microsoft/RulesEngine/wiki/Use-Case#inputs)
* [User Basic Info](https://github.com/microsoft/RulesEngine/wiki/Use-Case#user-basic-info)
* [Users Order Information](https://github.com/microsoft/RulesEngine/wiki/Use-Case#users-order-information)
* [Users Telemetry Information](https://github.com/microsoft/RulesEngine/wiki/Use-Case#users-telemetry-information)

1
docs/_config.yml Normal file
View File

@ -0,0 +1 @@
theme: jekyll-theme-cayman

143
docs/index.md Normal file
View File

@ -0,0 +1,143 @@
## Description
RulesEngine is a highly extensible library to build rule based system using C# expressions
## Features
- Json based rules defination
- Multiple input support
- Dynamic object input support
- C# Expression support
- Extending expression via custom class/type injection
- Scoped parameters
- Post rule execution actions
## Installation
Nuget package: [![nuget](https://img.shields.io/nuget/dt/RulesEngine)](https://www.nuget.org/packages/RulesEngine/)
## Basic Usage
### Create a workflow file with rules
```json
[
{
"WorkflowName": "Discount",
"Rules": [
{
"RuleName": "GiveDiscount10",
"Expression": "input1.country == \"india\" AND input1.loyalityFactor <= 2 AND input1.totalPurchasesToDate >= 5000 AND input2.totalOrders > 2 AND input3.noOfVisitsPerMonth > 2"
},
{
"RuleName": "GiveDiscount20",
"Expression": "input1.country == \"india\" AND input1.loyalityFactor == 3 AND input1.totalPurchasesToDate >= 10000 AND input2.totalOrders > 2 AND input3.noOfVisitsPerMonth > 2"
}
]
}
]
```
### Initialise RulesEngine with the workflow:
```c#
var workflowRules = //Get list of workflow rules declared in the json
var re = new RulesEngine.RulesEngine(workflowRules, null);
```
### Execute the workflow rules with input:
```c#
// Declare input1,input2,input3
var resultList = await re.ExecuteAllRulesAsync("Discount", input1,input2,input3);
//Check success for rule
foreach(var result in resultList){
Console.WriteLine($"Rule - {result.Rule.RuleName}, IsSuccess - {result.IsSuccess}");
}
```
This will execute all the rules under `Discount` workflow and return ruleResultTree for all rules
**Note: input passed to rulesEngine can be of a concrete type, an anonymous type or dynamic(Expandobject). In case of dynamic object, RulesEngine will internally convert to an anonymous type**
### Using custom names for inputs
By Default, RulesEngine will name the inputs as input1, input2, input3... respectively.
It is possible to use a custom name in rules by passing input as `RuleParameter`
```json
[
{
"WorkflowName": "DiscountWithCustomInputNames",
"Rules": [
{
"RuleName": "GiveDiscount10",
"Expression": "basicInfo.country == \"india\" AND basicInfo.loyalityFactor <= 2 AND basicInfo.totalPurchasesToDate >= 5000 AND orderInfo.totalOrders > 2 AND telemetryInfo.noOfVisitsPerMonth > 2"
},
{
"RuleName": "GiveDiscount20",
"Expression": "basicInfo.country == \"india\" AND basicInfo.loyalityFactor == 3 AND basicInfo.totalPurchasesToDate >= 10000 AND orderInfo.totalOrders > 2 AND telemetryInfo.noOfVisitsPerMonth > 2"
}
]
}
]
```
Now we can call rulesEngine with the custom names:
```c#
var workflowRules = //Get list of workflow rules declared in the json
var re = new RulesEngine.RulesEngine(workflowRules, null);
// Declare input1,input2,input3
var rp1 = new RuleParameter("basicInfo",input1);
var rp2 = new RuleParameter("orderInfo", input2);
var rp3 = new RuleParameter("telemetryInfo",input3);
var resultList = await re.ExecuteAllRulesAsync("DiscountWithCustomInputNames",rp1,rp2,rp3);
```
## 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.
RulesEngine supports two type of ScopedParams:
- GlobalParams
- LocalParams
### GlobalParams
GlobalParams are defined at workflow level and can be used in any rule.
#### Example
```json
//Rule.json
{
"WorkflowName": "workflowWithGlobalParam",
"GlobalParams":[
{
"Name":"myglobal1",
"Expression":"myInput.hello.ToLower()"
}
],
"Rules":[
{
"RuleName": "checkGlobalEqualsHello",
"Expression":"myglobal1 == \"hello\""
},
{
"RuleName": "checkGlobalEqualsInputHello",
"Expression":"myInput.hello.ToLower() == myglobal1"
}
]
}
```
These rules when executed with the below input will return success
```c#
var input = new RuleParameter("myInput",new {
hello = "HELLO"
});
var resultList = await re.ExecuteAllRulesAsync("workflowWithGlobalParam",rp);
```