reggaeguitar
reggaeguitar

Reputation: 1804

Dynamic LINQ Expression

I'm trying to implement this How to specify dynamic field names in a Linq where clause? and getting a compiler error that says:

Cannot resolve method 'Where(System.Linq.Expressions.LambdaExpression

public class Employee
{
    public string Name { get; private set; }
    public int Salary { get; private set; }

    public Employee(string name, int salary)
    {
        Name = name;
        Salary = salary;
    }
}

Then in main method of console app

var employees = new List<Employee>
{
    new Employee("Bob", 45000),
    new Employee("Jane", 25000),
    new Employee("Jim", 5)
};

var eParam = Expression.Parameter(typeof(Employee), "e");

var comparison = Expression.Lambda(
    Expression.LessThan(
        Expression.Property(eParam, "Salary"),
        Expression.Constant(40000)),
    eParam);
var c = from e in employees.Where(comparison) // COMPILER ERROR HERE!!!
    select new {e.Name, e.Salary};

I'm using System.Linq and System.Linq.Expressions. What am I doing wrong here?

EDIT:

The answer is to strongly type the comparison variable and call Compile on it like

var comparison = Expression.Lambda<Func<Employee, bool>>(
    Expression.GreaterThan(
        Expression.Property(eParam, "Salary"),
        Expression.Constant(40000)),
    eParam).Compile();

The query can also be written in method syntax like

var b = employees.Where(comparison);

Instead of calling .Compile(), one can call .AsQueryable() before .Where() on employees also.

Upvotes: 3

Views: 3411

Answers (1)

MarcinJuraszek
MarcinJuraszek

Reputation: 125660

  1. Your expression has to be strongly typed:

    var comparison = Expression.Lambda<Func<Employee, bool>>(... 
    
  2. Source has to be IQueryable. Call AsQueryable() on your list before calling Where.

Upvotes: 7

Related Questions