RulesEngine icon indicating copy to clipboard operation
RulesEngine copied to clipboard

Optional parameters for method calls not supported by expression evaluation

Open rklec opened this issue 1 year ago • 0 comments

STR

Define a rule as following:

{
      "RuleName": "TestPdfAttachmentContent1",
      "Expression": "pdfAttachments[0].PdfContentContainsSubstring(\"Mahnung\")"
}

(That input/RuleParameter is of course defined, it's not what matters here.)

If I catch all CLR exceptions while debugging, I get the following exception:

RulesEngine.Exceptions.RuleException
  HResult=0x80131500
  Nachricht = Error while compiling rule `TestPdfAttachmentContent1`: No applicable method 'PdfContentContainsSubstring' exists in type 'PdfAttachmentValidator'
  Quelle = RulesEngine
  Stapelüberwachung:
   bei RulesEngine.HelperFunctions.Helpers.HandleRuleException(Exception ex, Rule rule, ReSettings reSettings)

  Diese Ausnahme wurde ursprünglich von dieser Aufrufliste ausgelöst:
    RulesEngine.HelperFunctions.Helpers.HandleRuleException(System.Exception, RulesEngine.Models.Rule, RulesEngine.Models.ReSettings)
    RulesEngine.ExpressionBuilders.LambdaExpressionBuilder.BuildDelegateForRule(RulesEngine.Models.Rule, RulesEngine.Models.RuleParameter[])
    RulesEngine.RuleCompiler.BuildRuleFunc(RulesEngine.Models.Rule, RulesEngine.Models.RuleParameter[])
    RulesEngine.RuleCompiler.GetDelegateForRule(RulesEngine.Models.Rule, RulesEngine.Models.RuleParameter[])
    RulesEngine.RuleCompiler.CompileRule(RulesEngine.Models.Rule, RulesEngine.Models.RuleExpressionType, RulesEngine.Models.RuleParameter[], System.Lazy<RulesEngine.Models.RuleExpressionParameter[]>)

Innere Ausnahme 1:
ParseException: No applicable method 'PdfContentContainsSubstring' exists in type 'PdfAttachmentValidator'

Not, however, and this is a general behavior I don't quite like the exception is silently ignored even though I have explicitly disabled EnableExceptionAsErrorMessage (see below).

Note this is not true, because the PdfAttachmentValidator has such a method, but with an optional second argument:

public class PdfAttachmentValidator
{
    public bool PdfContentContainsSubstring(string substring, bool caseInsensitive = true)
    {
        return true;
    }
}

And yes, I've obviously injected the type:

      var engineSettings = new ReSettings()
        {
            CustomActions = // ...
            CustomTypes =
            [
                typeof(PdfAttachmentValidator)
            ],
            EnableExceptionAsErrorMessage = false
        };
     
        new RulesEngine.RulesEngine(mailWorkflows, engineSettings);

What happens

Apparently, it cannot find PdfContentContainsSubstring("Mahnung") as it cannot find the method signature PdfContentContainsSubstring(string substring, bool caseInsensitive = true).

What should happen

Just call PdfContentContainsSubstring with PdfContentContainsSubstring("Mahnung"), ignoring the optional parameter.

Workaround

Changing it like this and passing the optional parameter explicitly, makes it magically work:

{
      "RuleName": "TestPdfAttachmentContent1",
      "Expression": "pdfAttachments[0].PdfContentContainsSubstring(\"Mahnung\", true)"
}

But this is superfluous, obviously. And I would like to avoid this for obvious reasons.

More information

Weirdly enough, even changing it to default does not work (for whatever reason):

{
      "RuleName": "TestPdfAttachmentContent1",
      "Expression": "pdfAttachments[0].PdfContentContainsSubstring(\"Mahnung\", default)"
}

The (handled) exception then is Unknown identifier 'default':

RulesEngine.Exceptions.RuleException
  HResult=0x80131500
  Nachricht = Error while compiling rule `TestPdfAttachmentContent1`: Unknown identifier 'default'
  Quelle = RulesEngine
  Stapelüberwachung:
   bei RulesEngine.HelperFunctions.Helpers.HandleRuleException(Exception ex, Rule rule, ReSettings reSettings)
   bei RulesEngine.HelperFunctions.Helpers.ToRuleExceptionResult(ReSettings reSettings, Rule rule, Exception ex)
   bei RulesEngine.RuleCompiler.CompileRule(Rule rule, RuleExpressionType ruleExpressionType, RuleParameter[] ruleParams, Lazy`1 globalParams)
   bei RulesEngine.RulesEngine.CompileRule(Rule rule, RuleExpressionType ruleExpressionType, RuleParameter[] ruleParams, Lazy`1 scopedParams)
   bei RulesEngine.RulesEngine.CompileRule(String workflowName, String ruleName, RuleParameter[] ruleParameters)
   bei RulesEngine.RulesEngine.<ExecuteActionWorkflowAsync>d__13.MoveNext()

  Diese Ausnahme wurde ursprünglich von dieser Aufrufliste ausgelöst:
    RulesEngine.HelperFunctions.Helpers.HandleRuleException(System.Exception, RulesEngine.Models.Rule, RulesEngine.Models.ReSettings)
    RulesEngine.ExpressionBuilders.LambdaExpressionBuilder.BuildDelegateForRule(RulesEngine.Models.Rule, RulesEngine.Models.RuleParameter[])
    RulesEngine.RuleCompiler.BuildRuleFunc(RulesEngine.Models.Rule, RulesEngine.Models.RuleParameter[])
    RulesEngine.RuleCompiler.GetDelegateForRule(RulesEngine.Models.Rule, RulesEngine.Models.RuleParameter[])
    RulesEngine.RuleCompiler.CompileRule(RulesEngine.Models.Rule, RulesEngine.Models.RuleExpressionType, RulesEngine.Models.RuleParameter[], System.Lazy<RulesEngine.Models.RuleExpressionParameter[]>)

Innere Ausnahme 1:
ParseException: Unknown identifier 'default'

System

    <TargetFramework>net8.0</TargetFramework>
<!-- ... -->
    <PackageReference Include="RulesEngine" Version="5.0.3" /> 

aka .NET 8

Windows 10

rklec avatar Aug 07 '24 15:08 rklec