Ignatella
Ignatella

Reputation: 61

IQueryable<T>.Contains Expression Tree with Expression parameter

I want to implement custom .Contains() method with the following syntax:

static IQueryable<T> IsContainedBy<T, K>(this IQueryable<T> source, List<K> items, Expression<Func<T, K>> exp)

This method should look for coincidence in items array. Expression<Func<T, K>> exp provides property of object to be used for comparison. I have written the following code:

private IQueryable<T> WhereIsContainedBy<T, K>(IQueryable<T> source, List<K> items, Expression<Func<T, K>> exp) {
   if (items == null || items.Count == 0)
        return source;
   MethodInfo containsMethod = typeof(List<K>).GetMethod("Contains", new[] { typeof(K) });

   MethodCallExpression a = 
        Expression.Call(Expression.Constant(items), containsMethod, new Expression[] { exp.Body
                   /* Expression.Constant("31212eb5-cd5d-4f77-858a-a7ddba8e3d2c")*/ });

   Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(a, Expression.Parameter(typeof(T)));

   return source.Where(lambda);
}

But i get the following error:

var source = new List<string>() { "31212eb5-cd5d-4f77-858a-a7ddba8e3d2c" };
var r = WhereIsContainedBy(_context.StageActions, source, a => a.StageActionId);
var a = await r.ToListAsync();

---

Where(s => List<string> { "31212eb5-cd5d-4f77-858a-a7ddba8e3d2c", }.Contains(a.StageActionId))' could not be translated.

But if I use commented Expression.Constant..... it works just fine.

Upvotes: 1

Views: 727

Answers (1)

Guru Stron
Guru Stron

Reputation: 142213

Try reusing parameter from selector expression (i.e. exp) instead of creating a new one for resulting expression :

Expression<Func<T, bool>> lambda = 
    Expression.Lambda<Func<T, bool>>(a, exp.Parameters[0]);

Upvotes: 2

Related Questions