0

I want to build a dynamic where expression to use over a list of objects.

var list = new List<Dummy>();
IQueryable<Dummy> queryableData = list.AsQueryable<Dummy>();
MethodCallExpression wherExpression =
                Expression.Call(typeof(Queryable), 
                                "Where",
                                new Type[] { typeof(Dummy) }, 
                                queryableData.Expression,
                                Expression.Lambda<Func<Dummy, bool>>(lambda.Body, lambda.Parameters.First()));

Update: lambda.Body

lambda.Body = {(((x.Title.Contains("Mihai") Or x.Description.Contains("Mihai")) Or x.Comments.Contains("Mihai")) Or x.User.Contains("Mihai"))}

And then call the where expression like:

var result = queryableData.Provider.CreateQuery<Dummy>(wherExpression).ToList();

The where clause builds properly and this is the result

{System.Collections.Generic.List`1[P.Dummy].Where(x => (((x.Title.Contains("Foo") Or x.Description.Contains("Foo")) Or x.Comments.Contains("Foo")) Or x.User.Contains("Foo")))}

When I try can call the where expression, I get

 var result = queryableData.Provider.CreateQuery<Dummy>(wherExpression).ToList();
 variable 'x' of type 'P.Dummy' referenced from scope '', but it is not defined

Do you have any idea why and could you help me fix it ?

Update This is how the expression is constructed:

var type = typeof(T);
var lambdaList = new List<Expression<Func<T, bool>>>();
foreach (var prop in type.GetProperties())
{
    if (prop.PropertyType == typeof(string))
    {
        ParameterExpression parameter = Expression.Parameter(type, "x");//{x}
        Expression expression = parameter;

        PropertyInfo pi = type.GetProperty(prop.Name);//Property
                expression = Expression.Property(expression, pi);//{x.Property}

         var containsFunc = Expression.Call(expression,
                    typeof(string).GetMethod("Contains"),
                    new Expression[] { Expression.Constant("Mihai") });
                Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(containsFunc, parameter);
                lambdaList.Add(lambda);

     }
}
Expression<Func<T, bool>> finalExpression = lambdaList.First();

foreach (Expression<Func<T, bool>> expression in lambdaList.Skip(1))
{
   finalExpression = finalExpression.Or(expression);
}
8
  • Is there a reason why you don't just call Where and pass just the inner expression inside? In any case, unwrapping a lambda expression is a bit more complicated than just using the same body and parameters :) What is it you actually want to do? Commented Jun 10, 2015 at 9:44
  • I do not have any control over the inner expression. I'm building it dynamically for different objects that have string properties. After I have my expression, I need to apply it to a list of the same type of objects and the ones used to construct the expression. Commented Jun 10, 2015 at 9:48
  • Okay, so you already have the inner expression. Just call queryableData.Where(theInnerExpression) and you're done :) Commented Jun 10, 2015 at 9:49
  • I already tried that, but the .where takes a Expression<Func<T,bool>> as an argument, while my innerExpression is a MethodCallExpression. queryableData.Where(lambda.Compile()) this throws the same exception Commented Jun 10, 2015 at 9:52
  • Try to create only the lambda that passed to the where as Luaan mentioned. How do you create the lambda? Please show this code. Commented Jun 10, 2015 at 10:00

1 Answer 1

1

Copy of comment:

I got your problem. You create a new ParameterExpression for EACH property. They're all called x but they're different instances. Create only one ParameterExpression called x and then loop over all properties.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.