2013-06-25 41 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