zzzprojects / Eval-Expression.NET

C# Eval Expression | Evaluate, Compile, and Execute C# code and expression at runtime.
https://eval-expression.net/
Other
459 stars 86 forks source link

Please consider supporting the ICustomTypeProvider interface #24

Closed rodro75 closed 6 years ago

rodro75 commented 6 years ago

Hi, I have a use case that doesn't seem to be covered yet by your very nice library.

In my app I have an existing data context which is made of a few dictionaries, because it's dynamic in nature.

I would like to give the user the ability to write conditions based on that data context, but it would be really nice if he/she could write something like Custom.BirthDate.Year > 1980 rather than Custom["BirthDate"].Year > 1980.

So I went ahead and implemented an ICustomTypeProvider in order to populate my object dynamically and have Eval.Execute read it as if it was a regular object, but I get a NullReferenceException.

I guess it would be a matter of checking for the interface and call GetCustomType() instead of GetType() before using the existing reflection algorythm.

Thanks.

JonathanMagnan commented 6 years ago

Hello @rodro75 ,

I'm not sure about your implementation about the ICustomTypeProvider but here are two differents solution.

Solution #1

Don't prefix dictionary key by the variable "custom". Directly use the key in your expression.

Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("BirthDate", new DateTime(1980, 04, 13));

var isBefore = Eval.Execute("BirthDate.Year < 1981", parameters);

Solution #2

Convert your Dictionary into an expando object.

Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("BirthDate", new DateTime(1980, 04, 13));

var expandoObject = new ExpandoObject();
var expandoDict = (IDictionary<string, object>)expandoObject;

foreach (var keyValue in parameters)
{
    expandoDict.Add(keyValue.Key, keyValue.Value);
}

var isBefore = Eval.Execute("Custom.BirthDate.Year < 1981", new { Custom = expandoObject });

Let me know if you can use one of this two solutions.

Best Regards,

Jonathan

rodro75 commented 6 years ago

Doh! I should have tried solution #2 before everything else :-D

Thank you very much for the instant reply!