Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expression for ICollection<T>.Any(Func<T, bool>)

Tags:

c#

linq

Let's assume I have following Models:

public class Department
{
    public ICollection<Employee> Employees { get; set; }
}

public class Employee
{
    public string Name { get; set; }
}

I want to build an Expression for this:

departments.Where(x => x.Employees.Any(y => y.Name.Contains("foo")))

I have following code:

var departmentParameterExpression = Expression.Parameter(typeof(Department), "x");
PropertyExpression departmentListProperty = { x.Departments } // Value of the Expression shown in the debugger, actual code is some property helper to get the property by Name
var employeeParameterExpression = Expression.Parameter(typeof(Employee), "y");
PropertyExpression employeeNameProperty = { y.Name } // Same as departmenListProperty
var employeeNameContainsString = Expression.Call(employeeNameProperty, typeof(string).GetMethod("Contains"), Expression.Constant(token));
var compiledExpression = Expression.Lambda<Func<Employee, bool>>(employeeNameContainsString, employeeParameterExpression).Compile();

var anyMethod = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(x => x.Name == "Any" && x.GetParameters().Length == 2 &&  x.GetGenericArguments().Length == 1).MakeGenericMethod(typeof(Employee));

var containsEmployeeWithSearchString = Expression.Call(departmentListProperty, anyMethod, Expression.Constant(compiledExpression);

Running the last line, gives me following error:

Static method requires null instance, non-static method requires non-null instance. Parameter name: instance

When I just have .GetMethods(BindingFlags.Static) I don't get any Any()-Method unfortunately.

How do I make this work?

like image 270
Stefan Schmid Avatar asked Feb 05 '23 12:02

Stefan Schmid


1 Answers

Any and Where are extension methods on Enumerable and thus are static by definition. The actual expression you are trying to build would be equivalent to:

Enumerable.Where(departments, 
                 x => Enumerable.Any(x.Employees,
                                     y => y.Name.Contains("foo")
                                     )
                )
like image 72
D Stanley Avatar answered Feb 08 '23 16:02

D Stanley