共用方式為


Generating the Lambda Expression dynamically

The last post, I showed a simple way to build a lexicon scanner in .NET. We can now extend on the scanner and build a parser that generates a Lambda expression that can be compiled and called for further use. The parser I used is just a top-down recursive parser that builds up the Expression tree. The main method is BodyExpression that returns the Expression object.

The class LambdaCalc, holds all the logic. You can pass a string that will get parsed into a lambda expression. For example:

LambdaCalc lc = new LambdaCalc("(a, b) => -a + 2 * b");

Console.WriteLine(lc.Function(1, 2));

Function is a property of a delegate type declared as:

 

public delegate double Func(params double[] args);

So, the way we pass arguments to our lambda calculator is through an array of doubles. Internally, in the generated lambda expression, all parameter references are converted into array references. The previous example would generate the following lambda expression:

 

args => (-args[0] + (2 * args[1]))

To generate a Lambda Expression, you need to use one of the Lambda static methods inside the Expression class. Using the generic version, allows us to strongly define the delegate that the lambda expression will map to. For our case, this is how I generated the Lambda expression:

Expression<Func> lambdaExpr = Expression.Lambda<Func>(body, this.funcParamsArg);

  • body: is an expression that got parsed using our BodyExpression method.
  • funcParamsArg: is of type ParameterExpression and it’s the argument that will get used by the lambda expression.

 

The BodyExpression method eventually calls also other methods inside the Linq Expression class, for example, we use Expression.Add(leftExpr, rightExpr), to generate the additive expression, and the same goes for multiplication and so on.

 

The thing that worth mentioning is that in order to use the argument from inside the body, you need to use the same ParameterExpression object, otherwise you would get the following exception when compiling your Lambda Expression:

 

System.InvalidOperationException: Lambda Parameter not in scope

I attached the code bellow for the parser. You need the code from LambdaCalcScanner for this to work.

LambdaCalc.cs

Comments