views:

243

answers:

1

I'm trying to use the Expression tree and Lamdba Expression objects in .Net 3.5 to allow me to dynamically calculate boolean expression entered by a user.

So far a user can create an expression tree consisting of BinarayExpressions that AND and OR values expressed as ParameterExpressions. I was then planning on creating a LambdaExpression based on that tree so that I could compile the expression into a delegate which I could then call. The issue I'm having is that I don't know how many input parameters the user will need so when I come to compile the expression into a delegate I don't know the method what the method signature should be until runtime.

So far I've come up with two possible solutions.

  1. Create a whole bunch of delegates like the Func<bool, bool, bool...> ones which can take as many parameters as I think a user might possibly need. This doesn't feel like the most elegant solution but I think it would work, until someone wants to use one more parameter than I've catered for.
  2. Pass in an array of values and somehow assign them to my parameters using the array indexer. I've thought about this but can't work out how it work.

NB: It needs to be quick so no boxing or anything like that.

+3  A: 

I did exactly this before, using the array approach (for Finguistics, as it happens). The trick is Expression.ArrayIndex:

    var arr = Expression.Parameter(typeof(int[]), "arr");
    var body = Expression.ArrayIndex(arr, Expression.Constant(1));
    var expr = Expression.Lambda<Func<int[], int>>(body, arr);
    var func = expr.Compile();

    int[] vals = { 7, 8, 9 };
    int i = func(vals);

The advantage of the array approach is that you can keep a strongly typed delegate type (Func<int[],int> or similar, no matter the number of arguments. And typed Invoke is much faster than DynamicInvoke.

If the values aren't all of the same type - that is doable too; let me know and I'll add an example.

Marc Gravell
That works a treat, thanks Marc. Can you post an example for when the types aren't the same, as I can foresee that being the next requirement... and I'm also interested to know how its done.
Jon Mitchell