2

Is there a way to set the context of the expression in Dynamic Expresso library, so that we can do something like the following:

interpreter.Eval("FirstName", new Parameter("person", new { FirstName="Homer", LastName="Simpson"}));

rather than

interpreter.Eval("person.FirstName", new Parameter("person", new { FirstName="Homer", LastName="Simpson"}));

Maybe we could have a another option that would say that the first parameter is to be used as the context for the expression.

I guess there could also be another version of Parse and Eval methods that simply takes the expression text and a simple object value that will serve as the expression context.

Other than that and the lack of support for dynamic types, I am really liking this library. I had worked on something similar, but had not added support for extension methods and generic method calls.

Thanks for the great library, Neal

Davide Icardi
  • 11,919
  • 8
  • 56
  • 77

2 Answers2

2

There isn't a built-in solution but you can simulate it in many ways:

Option 1: Inject an expression

var workingContext = new { FirstName = "homer" };

var workingContextExpression = Expression.Constant(workingContext);
var firstNameExpression = Expression.Property(workingContextExpression, "FirstName");

var interpreter = new Interpreter();
interpreter.SetExpression("FirstName", firstNameExpression);

Assert.AreEqual(workingContext.FirstName, interpreter.Eval("FirstName"));

Basically I inject an expression using SetExpression method. The injected expression is the property that you want to be available.

Option 2: Use this/me/it variable

You can inject a variable that will contain your working object. I usually call it this (or me or it depending on the application).

var workingContext = new { FirstName = "homer" };

var interpreter = new Interpreter();
interpreter.SetVariable("this", workingContext);

Assert.AreEqual(workingContext.FirstName, interpreter.Eval("this.FirstName"));

Option 3: A combination of the previous solutions

var workingContext = new { FirstName = "homer" };

var interpreter = new Interpreter();
interpreter.SetVariable("this", workingContext);
var firstNameExpression = interpreter.Parse("this.FirstName").LambdaExpression.Body;
interpreter.SetExpression("FirstName", firstNameExpression);

Assert.AreEqual(workingContext.FirstName, interpreter.Eval("FirstName"));

Equal to the first solution but I generate the expression using the parser itself.

Consider that all solutions assume that you must have an Interpreter instance for each context.

Disclaimer: I'm the author of Dynamic Expresso library.

Davide Icardi
  • 11,919
  • 8
  • 56
  • 77
  • Hi Davide, thanks for responding so quickly. Yes, I can see how that approach would work for Eval, but it seems that we would not be able to use Parse to build a function in this manner. I would be better if the the variable "this" could be a parameter instead. – user3574702 Apr 28 '14 at 16:17
  • What I really want to do is something like this: var interpreter = new Interpreter(); var parameter = Expression.Parameter(typeof(Person), "this"); interpreter.SetExpression("FirstName", Expression.Property(parameter, "FirstName")); interpreter.SetExpression("LastName", Expression.Property(parameter, "LastName")); Func func = interpreter.Parse>("FirstName", "this"); But of course, the parameter name argument on the Parse function would need to be the parameter that I created in the beginning. – user3574702 Apr 28 '14 at 16:30
  • Unless I am mistaken, one option would be to simply make the following method of the interpreter class protected rather than private: Expression ParseExpression(string expressionText, Type expressionType, params ParameterExpression[] parameters) We could then inherit from your interpreter and leverage your great parser for these types of scenarios. Once I had the parsed expression tree, I could compile it using the following line: Expression.Lambda(expression, parameter).Compile(); – user3574702 Apr 28 '14 at 16:48
  • @user3574702 Yes I will think about it. I have just created a new issue on https://github.com/davideicardi/DynamicExpresso/issues/18 – Davide Icardi Apr 28 '14 at 17:01
  • Thanks Davide! I really like the SetExpression capabilities and this would allow us to inherit from the interpreter and use parameters in these expressions. Kind Regards, Neal Borelli – user3574702 Apr 28 '14 at 17:43
1

Starting with DynamicExpresso v2.13.0, it's possible to define a variable named "this", that will be used for implicit resolution:

var target = new Interpreter();
target.SetVariable("this", new { FirstName="Homer", LastName="Simpson"});

// 'this' variable is used implicitly
Assert.AreEqual("Homer", target.Eval("FirstName"));

// 'this' variable can also be used explicitly
Assert.AreEqual("Homer", target.Eval("this.FirstName"));
Métoule
  • 13,062
  • 2
  • 56
  • 84