This post is part of a series about building a simple mathematical expression evaluator. For previous posts and full source code see Table of Contents.

Introduction

In previous part we added support for variables but it has a big disadvantage: values of the variables are bound by position and not by name. This means that you should pass values for the variables in the same order as they appear in the expression. For example the following test will fail:

On the other hand binding by name has following advantages: If you change the expression you do not have to worry about keeping order of the variables you pass in sync. So in this post we are going to change expression evaluator to bind parameters by name. We will also add a new overload for better performance when we need to evaluate same expression with different parameter values.

Binding Variables by Name

The easiest way to pass variables with their name is to pass a dictionary of variables with variable name acting as a key. While this will work it is not the most elegant and readable solution. A better solution will be to pass an anonymous object with properties pointing to the variable values. So our first task is to make the following test pass:

Passing Parameters with Anonymous Objects

The first thing we need to do when an object containing variables is passed is to enumerate its properties and build a dictionary of variable name and value. Once we have the dictionary we pass it to the private Enumerate method which we implemented in previous post. The code is pretty straightforward:

As it is based on features introduced in .Net 4 this overload will only be available for users using .Net 4 or upper.

To implement this feature we need to inherit ExpressionEvaluator class from DynamicObject and override TryInvokeMember method. This method will get invoked whenever a method is called which should be resolved at runtime. Parameter names as well as values are passed to this method. This allows us to build a dictionary of arguments and pass them to the Enumerate method showed in this post. This is how we do it:

Now we can specify parameter names in a more elegant way without having to construct an anonymous object.

Improving Expression Evaluator Performance

Let’s say you have an expression which you want to evaluate multiple times but with different parameters. Currently the Evaluate method will parse and compile the expression tree for every evaluation even thought the expression is same every time. As the compilation of expression trees is an expensive operation it will be better if the library allowed to compile the expression only once and execute it multiple times with different values of variables.

To support this scenario we will add a new method Compile which takes an expression and returns a delegate which you can execute multiple times. Here is an example of what we want to do:

The Compile method is the same as the Evaluate method with the only difference being that it returns the compiled delegate instead of invoking it. This means we can extract a new method and use it from both methods. I will not show the full source code here as it is does not add any new parsing logic and the code is available at github.

Conclusion

In this post we improved expression evaluator and added support for binding variables by name. We also added a new overload for specifying variables as named arguments. Finally we added a new method returning compiled delegate to avoid multiple compilations.

In the next post we will add support for unary negation. Do not miss it