dynamicexpresso / DynamicExpresso

C# expressions interpreter
http://dynamic-expresso.azurewebsites.net/
MIT License
2.02k stars 379 forks source link

If we use interpreter.SetDefaultNumberType(DefaultNumberType.Decimal) , then we can't access any default library like string related or Math related functions etc. #311

Closed ATEEKGIT closed 3 months ago

ATEEKGIT commented 3 months ago

If we use interpreter.SetDefaultNumberType(DefaultNumberType.Decimal); as in code below.

interpreter = new Interpreter().SetDefaultNumberType(DefaultNumberType.Decimal);

After this if we try to evaluate below string for a loaded variable strVariable , Below expression will not evaluate.

strVariable.Substring(0, 40)

if we create the interpreter with this interpreter = new Interpreter() then above expression will evaluate.

I have tried to add reference for the string and Math lib as below , but it still does not work , it only works if we remove the SetDefaultNumberType option.

 interpreter = interpreter.Reference(typeof(System.String));
 interpreter = interpreter.Reference(typeof(System.Math));

can someone help on this issue. as we need to set Default Number Type and also have some access to libraries for extension methods etc.

davideicardi commented 3 months ago

Thank you @ATEEKGIT for the bug report. Do you think it is possible for you to create a PR with an unit test that demonstrate the bug? Otherwise I will try to work on it in the future.

ATEEKGIT commented 3 months ago

thanks bro for attention , unfortunatly i am not familiar much with github and jsut reach here to report bug as it was a major issue for us in production. The problem can be reproduced with just just 2 lines of code. ,

a. create instance of interpreter as below. interpreter = new Interpreter().SetDefaultNumberType(DefaultNumberType.Decimal);

b. and try to evaluate andy of the function of Math or String or DateTime , it will not work.

and then you may pass to interprerter any reference to any library and it will not work.

davideicardi commented 3 months ago

I investigate the problem, and it was the expected behavior. Substring method in .NET (https://learn.microsoft.com/en-us/dotnet/api/system.string.substring?view=net-8.0#system-string-substring(system-int32-system-int32)) it is not defined for Decimal type, so if you force all types to be decimal it will not work unless you perform a cast to int.

var interpreter2 = new Interpreter().SetDefaultNumberType(DefaultNumberType.Decimal);
interpreter2.SetVariable("a", a);
// expected to throw because Substring is not defined for decimal
Assert.Throws<NoApplicableMethodException>(() => interpreter2.Eval("a.Substring(0, 2)"));
// It works if we cast to int
Assert.AreEqual("AA", interpreter2.Eval("a.Substring((int)0, (int)2)"));

Why do you use SetDefaultNumberType in your scenario?