mparlak / Flee

Fast Lightweight Expression Evaluator
607 stars 119 forks source link

NullReferenceException when trying to call DateTime methods #64

Open jamiecoh opened 5 years ago

jamiecoh commented 5 years ago

When using methods on DateTime such as AddDays in an expression the following works as expected:

var eng = new CalculationEngine();
var ctx = new ExpressionContext();
ctx.Variables.Add("now", DateTime.Now);
eng.Add("d", "now.AddDays(1)",ctx);
eng.Add("res", "d", new ExpressionContext());
var result = eng.GetResult("res");

However, when trying to execute AddDays in the following (similar) manner, you get a NRE from FLEE:

var eng = new CalculationEngine();
var ctx = new ExpressionContext();
ctx.Variables.Add("now", DateTime.Now);
eng.Add("d", "now",ctx);
eng.Add("res", "d.AddDays(1)", new ExpressionContext());
var result = eng.GetResult("res");

This error occurs in Flee.InternalTypes.Expression:

public object Evaluate()
{
    return _myEvaluator(_myOwner, _myContext, _myContext.Variables);
}

Object reference not set to an instance of an object.

Here is the StackTrace

at Flee Expression(Object , ExpressionContext , VariableCollection ) at Flee.InternalTypes.Expression1.Evaluate() at Flee.CalcEngine.InternalTypes.GenericExpressionResultPair1.Recalculate() at Flee.CalcEngine.PublicTypes.CalculationEngine.FixTemporaryHead(IDynamicExpression expression, ExpressionContext context, Type resultType) at Flee.InternalTypes.Expression`1..ctor(String expression, ExpressionContext context, Boolean isGeneric) at Flee.PublicTypes.ExpressionContext.CompileDynamic(String expression) at Flee.CalcEngine.PublicTypes.CalculationEngine.Add(String atomName, String expression, ExpressionContext context) at FleeTests.Program.Main(String[] args)

jamiecoh commented 5 years ago

Workaround for this issue is to add an Import with the same functionality:

public static class HelperFunctions
{      
    // This shouldn't be necessary - I can usually execute an objects methods directly in an expression
    public static DateTime AddDays(DateTime date, int days)
    {
        return date.AddDays(days);
    }
}

Remember to import the helper class, and then use AddDays(d,1) as the expression

var eng = new CalculationEngine();
var ctx = new ExpressionContext();
ctx.Imports.AddType(typeof(HelperFunctions));
ctx.Variables.Add("now", DateTime.Now);
eng.Add("d", "now",ctx);
eng.Add("res", "AddDays(d,1)", ctx);
var result = eng.GetResult("res");