Search code examples
c#expression-trees

How to write List All method using expression trees?


I have below code snippet.

var list= new List<CustomClass>(){ new CustomClass(){Id=10}};
var result= list.All(a=>a.Id==10);

How can we write it in an Expression Tree?

Purpose: It's part of a bigger expression tree logic which we are implementing, I am just stuck at generating the expression tree for "All" method of the list.

Thanks


Solution

  • It isn't exactly clear what you are trying to do, but let's start from here...

    This is the Enumerable.All method:

    static readonly MethodInfo allTSource = (from x in typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public)
                                             where x.Name == nameof(Enumerable.All)
                                             let args = x.GetGenericArguments()
                                             where args.Length == 1
                                             let pars = x.GetParameters()
                                             where pars.Length == 2 &&
                                                 pars[0].ParameterType == typeof(IEnumerable<>).MakeGenericType(args[0]) &&
                                                 pars[1].ParameterType == typeof(Func<,>).MakeGenericType(args[0], typeof(bool))
                                             select x).Single();
    

    Then the lambda expression used in .All(...):

    // a => 
    var par = Expression.Parameter(typeof(CustomClass), "a");
    
    // a.Id
    var id = Expression.Property(par, nameof(CustomClass.Id));
    
    // 10
    var val = Expression.Constant(10);
    
    // a.Id == 10
    var eq = Expression.Equal(id, val);
    
    // a => a.Id == 10
    var lambda = Expression.Lambda<Func<CustomClass, bool>>(eq, par);
    

    Then the problem: it isn't clear if the list is a constant or an external expression... I don't know how to connect my code to yours... Let's say for simplicity that it is a constant:

    // Unclear what lst should be, a parameter of an external lambda or a constant
    var lst = Expression.Constant(list);
    
    // list.All(...)
    var all = Expression.Call(allTSource.MakeGenericMethod(typeof(CustomClass)), lst, lambda);
    
    // () => list.All(...)
    Expression<Func<bool>> exp = Expression.Lambda<Func<bool>>(all);
    Func<bool> fn = exp.Compile();
    bool res = fn();