In the previous example, rules, whether triggering events or payments, were relatively simple and the match was always successful, but in real life rules can be more complex and there are rules where gaining points can fail. For example, if we transfer partners’ points to the current platform, we need to check whether the partners are legal, and prevent points from being transferred if they are illegal.
Create a custom rule
In the previous example of Expression, only the methods provided in the System library can be used for logical judgment. For example, string has a built-in method, int has a built-in method. If you want to use custom methods, you need to do additional processing. First you need a static method in a static class.
public static class PartnerUtil
{
private static readonly List<string> ValidPartnerNames = new()
{
"AS"."DF"."GH"
};
public static bool ValidatePartner(string partnerName) => ValidPartnerNames.Contains(partnerName);
}
Copy the code
There are a few caveats here
- We define a static class to handle partner related methods and provide static methods for partner validation.
- This is just a simple validation of name validity. We assume that we support only three partners and the rest are illegal.
- Even if it is just name validation, these names should not be hard-coded in code, but configured by operations personnel and retrieved at run time, as an example.
- The static method that you provide doesn’t have to return a bool, but you can go through Expression and get a bool, so again, this is just a very simple example.
- The static method here can even be an extension method.
Register custom rules
When we initialize RulesEngine we need to register the previous custom rule so that it can be used in the rule engine.
var reSettings = new ReSettings()
{
CustomTypes = new[] {typeof(PartnerUtil)}
};
_engine = new RulesEngine.RulesEngine(workflowRules, null, reSettings);
Copy the code
Our previous RulesEngine was initialized with just workflowRules, so we need to use another overloaded constructor to pass in our custom reSettings. As an aside, the second parameter not passed is logger, which is not in our example.
Use custom rules
We can then use the rules we defined earlier in the rule. Here is a Workflow for the new definition
{
"WorkflowName": "Transformation"."Rules": [{"RuleName": "TransForMore"."SuccessEvent": "Transfer points succeed"."RuleExpressionType": "LambdaExpression"."Expression": "PartnerUtil.ValidatePartner(partnerName)"."ErrorMessage": "Transfer points failed, invalid partner name"."ErrorType": "Error",}}]Copy the code
This rule differs from the others in the following ways
- Expression Uses a custom rule.
- ErrorType and ErrorMessage were introduced to determine what happens if a rule fails to match.
- ErrorType can be Warning or Error,
- ErrorMessage corresponds to SuccessEvent, which should be a message sent after a SuccessEvent, but the function after a failure does not accept parameters, so I really can’t find where this ErrorMessage is used.
Also, SuccessEvent is used instead of actions.onsuccess is just lazy.
Then, don’t forget to use rules as injection parameters
input.Add(new RuleParameter("partnerName", args.GetProperty("partnerName").GetString()));
Copy the code
Finally, we need to subscribe to our rules to trigger failed events
resultList.OnFail(() =>
{
response = new RuleResponse() {Message = "Trigger rule failed"};
});
Copy the code
We can see that this event, unlike the OnSuccess event, has an argument that receives SuccessEvent, so the ErrorMessage in the rule is lost. Here is the source code for OnFail.
public static List<RuleResultTree> OnFail(
this List<RuleResultTree> ruleResultTrees,
ListofRuleResultTreeExtension.OnFailureFunc onFailureFunc)
{
if (ruleResultTrees.All<RuleResultTree>((Func<RuleResultTree, bool>) (ruleResult => ! ruleResult.IsSuccess))) onFailureFunc();return ruleResultTrees;
}
public delegate void OnFailureFunc();
Copy the code
Call the debugging
run
Legal partner, transfer successful
Illegal partner, transfer failed