0

I recently stumpled upon the problem to dynamically create Linq expressions. Most examples I found deal with the rather simple task, just comparing one property of a given database entity with a single parameter.

I would like to compare related object with a specific property. I already create a contains expression. But I would like to create a dynamic doesn't contains expression.

Here is the specific code with the explicit LINQ query I would to reproduce in generic form.

var schools = new List<School>
            {
               new School("School1") { Students = new List<Student>() { new Student("Student1"), new Student("Student2") }},
               new School("School1") { Students = new List<Student>() { new Student("Student1"), new Student("Student2") }},
               new School("School2") { Students = new List<Student>() { new Student("Student3"), new Student("Student4") }},
               new School("School3") { Students = new List<Student>() { new Student("Student3"), new Student("Student5") }},
            };

string searchValue = "Student3";

// Explicit query (will be the result)
var query = schools.Where(x => !x.Students.Any(y => y.Name.Contains(searchValue)));

Where "Students" is of the type List and the property "Name" is of the type string. "Schools" contains the Students list.

I tried something like this but I'm not sure is the best practice to achieve.

public class NotAnyContainsClass
{
    private static readonly MethodInfo MethodContains = typeof(Enumerable).GetMethods(
           BindingFlags.Static | BindingFlags.Public)
       .Single(m => m.Name == nameof(Enumerable.Contains) && m.GetParameters().Length == 2);
    private static readonly MethodInfo MethodAny = typeof(Enumerable).GetMethods(
            BindingFlags.Static | BindingFlags.Public)
        .Single(m => m.Name == nameof(Enumerable.Any) && m.GetParameters().Length == 2);

    private static readonly MethodInfo EnumerableCastMethod = typeof(Enumerable).GetMethod("Cast");
    private static readonly MethodInfo GenericContainsMethod = MethodContains.MakeGenericMethod(typeof(object));
    private static readonly MethodInfo GenericAnyMethod = MethodAny.MakeGenericMethod(typeof(object));


    public Expression CreateExpression(string searchString)
    {
        //Query.<OuterList>.Where(x => !x.<InnerList>.Any(y => y.Name.Contains(searchValue)));
        //...
    }
}

And the caller would be

var operation = new NotAnyContainsClass();
var expression = operation.CreateExpression(searchValue, /* I think need more parameters */);
var query = expression(schools);

Is it possible to build a Linq expression like this dynamically ? After it will be used for generate SQL query with Linq.

araqiel
  • 5
  • 3

0 Answers0