microsoft / RulesEngine

A Json based Rules Engine with extensive Dynamic expression support
https://microsoft.github.io/RulesEngine/
MIT License
3.47k stars 528 forks source link

Cannot use math from System.Math #582

Closed druman-ri closed 4 months ago

druman-ri commented 4 months ago

Hi, I'm wondering if it's possible to utilize the methods provided in the System.Math namespace. I'd love to simplify some rules with eg. Min/Max/Clamp methods eg. limit a property to be in specified range for example:

{
    "RuleName": "Check if math methods work",
    "Expression": "true",
    "Actions": {
        "OnSuccess": {
            "Name": "SetValue",
            "Context": {
                "NewValue": "Math.Min(Item.Value, 20)"
            }
        }
    }
}

this results with exception {"Exception while executing SetValueAction: No applicable method 'Min' exists in type 'Math'"} even with added System.Math to CustomTypes in ReSettings

var settings = new ReSettings
{
    CustomTypes = [typeof(CompareExtensions), typeof(Math)] // added System.Math
};

When rule has full namespace declaration: System.Math.Min(Item.Value, 20) it results with even worse exception: {"Exception while executing SetValueAction: Enum value 'Min' is not defined in enum type 'System.Math'"}

When rule has only Min(Item.Value, 20) then it results with: {"Exception while executing SetValueAction: No applicable method 'Min' exists in type 'Item'"}

Do you have any solutions? Min/Max/Clamp are must have ones, but it would be nice to have more math methods working out of the box.

RenanCarlosPereira commented 4 months ago

you don't need to add the Math to your RESettings: here's a sample using RuleExpressionParser

var parameter = new RuleParameter("Board", new { Item = new { Value = 10 } });
var parser = new RuleExpressionParser(new ReSettings());
const string expression = @"Math.Min(Item.Value, 20)";
var result = parser.Evaluate<decimal>(expression, new[] { parameter });
Console.WriteLine(result);
druman-ri commented 4 months ago

oh yeah, now the result is different, I must have missed something. Additionally, what I forgot about is that the type was decimal? and needed to do Item.Value.Value.