TheNerd
TheNerd

Reputation: 339

Dynamic Linq Expression for IEnumerable<int>.contains(MemberExpression)

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?

Upvotes: 6

Views: 5751

Answers (3)

Mahmoud Moravej
Mahmoud Moravej

Reputation: 9034

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);

Upvotes: 0

p.s.w.g
p.s.w.g

Reputation: 149020

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);

Upvotes: 15

Yaser Moradi
Yaser Moradi

Reputation: 3317

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

Upvotes: 0

Related Questions