Assign variable to Expression<Func<TSource, bool>>

451 Views Asked by At

Using Net 4.5.1

Have the following class Respondent:

namespace Whatever {
  public class Respondent {
    public int x { get; set; }
    public int y { get; set; }

    public static Expression<Func<Respondent, bool>> compareXY(int value) {
      return x => ((x.x * 100) + x.y) > value;
    }
  }
}

Lets say I want to pass the body of the lamdba around. Getting it by:

... some function ...
Type MemberType = typeof(<this class>).Assembly.GetType("Whatever.Respondent");

object[] parameters = new object[] { <populate with integer value> };

var expr = MemberType
  .GetMethod(MemberFunctionName, BindingFlags.Public | BindingFlags.Static)
  .Invoke(null, parameters) as LambdaExpression;

return expr.body

Problem is that the variable x (i.e. Respondent) is not defined. For example, the functional expression compareXY might be included in a larger expression tree that derives from a series of predicates (i.e. standing for comparisons, literals, functions, etc):

...function returning Expression<Func<Respondent, bool>>...
Expr together = Predicates.Aggregate(
  (prev, next) => new And { Operands = new Expr[] { prev, next}  }
);

Expression composition = together.getExpression(context);  <-- here resolving compareXY
return Expression.Lambda(composition, new ParameterExpression[] { context });

Basically, the body of the lambda returned from compareXY has to have a variable/parameter x set to the Respondent type.

EDIT, Getting the following error:

 {"variable 'x' of type 'Charting.Models.Respondent' referenced from scope '', 
 but it is not defined"}

Question is how to define the variable x to the body of the Lambda?

1

There are 1 best solutions below

2
On

I'm not entirely sure there's a question in there, but I think you answered it:

The body of the LambdaExpression doesn't include the parameters. Those would be in expr.Parameters. If you need to re-use the body of the lambda, you'll need to recreate it.

Alternatively, you can pass the lambda in its entirety, then call use an InvokeExpression to invoke the lambda.

EDIT: To answer your question, you must pass the parameters along with the body of the expression. The parameter used must be reference equivalent to what's in expr.Parameters. You can't substitute it for a newly created ParameterExpression.