Question

I want to create an expression using the Linq Expression tree to simulate this:

List<int> ids = new List<int>();

// Fill ids with data

db.Where(a => ids.Contains(a.Id));

This is where I have gotten, but I am still missing something:

MemberExpression me = Expression.Property(pe, typeof(T).GetProperty(property));

Expression callContains = Expression.Call(typeof(System.Linq.Enumerable), "Contains", new Type[] { me.Type }, me);

How can I do what I want to do properly?

Was it helpful?

Solution

Because Contains is an extension method, you'll also have to provide the ids collection as a parameter, in this case, as a ConstantExpression.

Your implementation might be slightly different, but it would look a bit like this:

public static IQueryable<T> DynamicContains<T, TProperty>(
    this IQueryable<T> query, 
    string property, 
    IEnumerable<TProperty> items)
{
    var pe = Expression.Parameter(typeof(T));
    var me = Expression.Property(pe, property);
    var ce = Expression.Constant(items); 
    var call = Expression.Call(typeof(Enumerable), "Contains", new[] { me.Type }, ce, me);
    var lambda = Expression.Lambda<Func<T, bool>>(call, pe);
    return query.Where(lambda);
}

db.DynamicContains("Id", ids);

OTHER TIPS

You can add reference to Mono.CSharp dll, then you can use Evaluator class to compile csharp codes on the fly then concat strings to create linq queries easily then compile them it's not slow, and it is easy

In complementary of @p-s-w-g answer, the DynamicNotContains is :

    public static IQueryable<T> DynamicNotContains<T, TProperty>(this IQueryable<T> query, string property, IEnumerable<TProperty> items)
    {        
        var pe = Expression.Parameter(typeof(T));
        var me = Expression.Property(pe, property);
        var ce = Expression.Constant(items);
        var call = Expression.Call(typeof(Enumerable), "Contains", new[] { me.Type }, ce, me);
        var lambda = Expression.Lambda<Func<T, bool>>(Expression.Not(call), pe);

        return query.Where(lambda);
    }
db.DynamicNotContains("Id", ids);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top