Dynamic where expression to use in linq

676 Views Asked by At

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);
}
1

There are 1 best solutions below

0
On BEST ANSWER

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.