1

Hello I would like to create a generic Expression Tree that returns a list contains result.

public static class Extension{
    public static List<T> WhereIn<T, T1>(IQueryable<T> query, IEnumerable<T1> keys, Expression<Func<T, T1>> param)
    {
    }
}

The problem is that I would also like to create something like this:

var result = Extension.WhereIn(customers.AsQueryable(), stringList, c => c.Number.ToString());

so far this would work for a static property name:

public static Expression<Func<T, bool>> FilterByCode<T, T1>(List<T1> codes, string propName)
{
    var methodInfo = typeof(List<T1>).GetMethod("Contains", 
        new Type[] { typeof(T1) });

    var list = Expression.Constant(codes);

    var param = Expression.Parameter(typeof(T), "j");
    var value = Expression.Property(param, propName);
    var body = Expression.Call(list, methodInfo, value);

    // j => codes.Contains(j.Code)
    return Expression.Lambda<Func<T, bool>>(body, param);
}
2
  • I don't get your question. What should WhereInA do? Can you hardcode expected expression or add an example of how it should work? Commented Jul 11, 2019 at 13:36
  • Basically the WhereIn (WhereInA had an A too much) method should create a contains Expression. But like you see in the second code Extension.WhereIn... It should get a queryable, a list and an expression as Parameter. The tricky part for me is to pass an expression that is not a member Expression but something like : c => c.Number.ToString() Commented Jul 11, 2019 at 19:26

1 Answer 1

3

Thanks to Marc Gravell I got the solution:

  public List<T> WhereIn<T, TValue>(IQueryable<T> source, IEnumerable<TValue> keys, Expression<Func<T, TValue>> selector)
  {
     MethodInfo method = null;
     foreach (MethodInfo tmp in typeof(Enumerable).GetMethods(
        BindingFlags.Public | BindingFlags.Static))
     {
        if (tmp.Name == "Contains" && tmp.IsGenericMethodDefinition
                                   && tmp.GetParameters().Length == 2)
        {
           method = tmp.MakeGenericMethod(typeof(TValue));
           break;
        }
     }
     if (method == null) throw new InvalidOperationException(
        "Unable to locate Contains");
     var row = Expression.Parameter(typeof(T), "row");
     var member = Expression.Invoke(selector, row);
     var values = Expression.Constant(keys, typeof(IEnumerable<TValue>));
     var predicate = Expression.Call(method, values, member);
     var lambda = Expression.Lambda<Func<T, bool>>(
        predicate, row);
     return source.Where(lambda).ToList();
  }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.