2013-08-28 71 views
4

我想使用LINQ表達式樹來模擬它來創建一個表達式:動態LINQ表達式爲IEnumerable的<int>。載有(MemberExpression)

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

// Fill ids with data 

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

這是我已經得到了,但我還是失去了一些東西:

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

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

我該如何做我想做的事情?

+0

我只有一個問題。你爲什麼要這樣做? –

+2

我正在構建一個使用linq的非常大且非常複雜的搜索機制。我有框架不允許訪問IQueryable對象,只有我們的自定義模型,所以我不能像我通常那樣鏈接查詢。相反,我根據所選的搜索選項逐個構建表達式。 – TheNerd

回答

9

由於Contains是擴展方法,因此您還必須提供ids集合作爲參數,在此例中爲ConstantExpression

您的實現可能會略有不同,但它看起來有點像這樣:

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

我沒有看到在你的方法的任何地方使用'property'參數,我想你的意思是'typeof(T).GetProperty(property)'(而不是「Id」)。 –

+1

@KingKing oops你是對的。謝謝,我已經糾正它。 –

+0

謝謝!這正是我所需要的,我看到我之前缺少的東西。 – TheNerd

0

您可以到Mono.CSharp DLL添加引用,那麼你可以使用計算器類編寫的飛行CSHARP代碼 然後CONCAT字符串容易 創建LINQ查詢然後編譯他們 它並不慢,而且很容易

0

在@pswg答案,動態包含互補是:

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); 
相關問題