2013-06-25 64 views
2

我有下面的代碼從大會獲得類型的集合,其中的類型是類:錯誤使用LINQ表達式變量,而不是lambda表達式時,直接

Assembly assembly = Assembly.LoadFile(DLLFile); 
var types = assembly.GetTypes().AsEnumerable().Where(x => x.IsClass); 

這工作正常,並符合市場預期。然而,我想將lambda表達式拉出到Linq Expression變量中(後面將在此方法的參數中使用它)。所以,我做了以下內容:

System.Collections.Generic.IEnumerable<System.Type>' does not contain a 
definition for 'Where' and the best extension method overload 
'System.Linq.Enumerable.Where<TSource>(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,int,bool>)' has some invalid arguments 

我明白,我表達不符合謂詞System.Func<TSource,int,bool>,但是Where功能有:

private Expression<Func<Type, bool>> _standardFilter = (x => x.IsClass); 
Assembly assembly = Assembly.LoadFile(DLLFile); 
var types = assembly.GetTypes().AsEnumerable().Where(_standardFilter); 

但是這不會有錯誤編譯超載,需要一個謂詞System.Func<TSource,bool>,據我所知可以工作。

我已經嘗試將assembly.GetTypes()(這是一個數組)的結果以幾種方式轉換爲列表,而沒有它幫助解決問題。

我也確定我已經得到了這個類的所有正確的using聲明,因爲這似乎是幾個人在我的谷歌搜索過程中遇到的問題。

在過去,我已經成功地使用同樣的技術在IQueryable集合,但我不明白爲什麼當Where功能可在IEnumerable收集這是不行的,應該接受我提供的謂詞。

非常感謝您的幫助。

+1

'表達>'和'功能<...>'是不一樣的東西。 – voithos

+0

'IQueryable '上的'Where'擴展方法接受'Expression >',這就是爲什麼你以前能夠做到這一點。這允許像EF這樣的東西傳入一個表達式並在以後進行編譯。但在'IEnumerable '上,它只接受'>'。 –

+0

因此,再次歸結爲我不注意到一個特定的詞!我真的應該退後一步,多關注我所設想的事情! – XN16

回答

2

請注意Enumerable擴展方法需要一個Func而不是一個表達式。所以你的論點是錯誤的輸入。

這與Entity Framework相反,Entity Framework需要表達式< Func>而不是普通的Func。

所以要注意方法簽名,它們是相似的,都可以用相同的lambda調用,但實際上是不同的!

其原因在於EF檢查Expression並將其轉換爲SQL代碼,而Linq to Object只是在內存中執行謂詞。

5

編譯表達式爲可執行代碼(代表):

var types = assembly.GetTypes().AsEnumerable().Where(_standardFilter.Compile()); 

由於@Kirk說,這是最好不要使用表達式目錄樹,如果你不打算去分析它。只需使用Func<Type, bool>類型的過濾器即可。

+3

甚至更​​好,不要將lambda放在表達式樹中。 –

+0

@KirkWoll完全贊同你:) –

0

你可以代替試試這個:

private Func<Type, bool> standardFilter; 
standardFilter = (type) => { 
    return type.IsClass; 
}; 

var types = assembly.GetTypes().AsEnumerable().Any(x => standardFilter(x)); 

然後你可以自由地改變你的standardFilter的實現。只要它需要一個Type並返回bool是否應該包含它,它將保持模塊化並完成我認爲你要做的事情。

+1

或只是私人Func standardFilter = type => type.IsClass; var types = assembly.GetTypes()。AsEnumerable()。Any(standardFilter); – jods