user3574702
user3574702

Reputation: 21

Ability to set the context of the expression

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

Upvotes: 2

Views: 1128

Answers (2)

Métoule
Métoule

Reputation: 14472

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"));

Upvotes: 1

Davide Icardi
Davide Icardi

Reputation: 12209

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.

Upvotes: 2

Related Questions