nreco / lambdaparser

Runtime parser for string expressions (formulas, method calls). Builds dynamic LINQ expression tree and compiles it to lambda delegate.
http://www.nrecosite.com/
MIT License
309 stars 55 forks source link

Failed DateTime.Now #22

Closed trrahul closed 4 years ago

trrahul commented 4 years ago

I used the simple code but it resulted in a null reference exception. Is this supported?

var varContext = new Dictionary<string, object>(); var lambdaParser = new NReco.Linq.LambdaParser(); Console.WriteLine(lambdaParser.Eval("System.DateTime.Now", varContext)); Console.Read();

image

VitaliyMF commented 4 years ago

You cannot access static methods / properties directly in the expression, this is by design (to guarantee that expressions may use only explicitly defined context).

It is possible to expose DateTime.Now in the following way:

varContext["DateTimeNow"] = (Func<DateTime>)(() => DateTime.Now);
Console.WriteLine(lambdaParser.Eval("DateTimeNow()", varContext));

another approach: usage of special 'API' objects in the context

public class DateTimeApi {
  public DateTime Now => DateTime.Now;
}

varContext["DateTime"] = new DateTimeApi();
Console.WriteLine(lambdaParser.Eval("DateTime.Now", varContext));
trrahul commented 4 years ago

Thanks. If I were to something like this, would it work?

varContext["DateTime"] = (Func<DateTime>)(() => DateTime);
Console.WriteLine(lambdaParser.Eval("DateTime.Now", varContext));
Console.WriteLine(lambdaParser.Eval("DateTime.UtcNow", varContext));

If so, it would be possible to give more static class contexts. I understand that "DateTime.Now()" is needed instead of "DateTime.Now", but is it possible to do this some other way?

I ask this because I tried DynamicExpresso and Flee, but both of them were not able to do what I wanted. I assigned a=1, b=2, c=a+b and then d = c+a. DynamicExpresso and Flee evaluated d to a+b1 instead of 4. But lambdaparser did it correctly so I tried more examples but it failed when I tested the DateTime.

VitaliyMF commented 4 years ago

varContext["DateTime"] = (Func)(() => DateTime);

this will not work because DateTime refers to System.Type. You need to pass an object that has properties/methods. You may use an approach with DateTimeApi to enable a syntax similar to C# (like "DateTime.Now") and add to DateTimeApi any properties/methods you want to expose for expressions.