2

我有以下代码从类型为类的程序集中获取类型集合:

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

这可以正常工作并且符合预期。但是,我想将 lambda 表达式提取到 Linq 表达式变量中(稍后将在此方法的参数中使用它)。所以我做了以下事情:

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

但是,这不会与错误一起编译:

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

我知道我的表达式不符合 predicate System.Func<TSource,int,bool>,但是该Where函数有一个重载,它需要一个 predicate System.Func<TSource,bool>,据我所知,它应该可以工作。

我已经尝试assembly.GetTypes()以多种方式将(这是一个数组)的结果转换为一个列表,而没有帮助解决这个问题。

我还确保我已经获得了using该课程的所有正确陈述,因为这似乎是几个人在我的谷歌搜索过程中遇到的问题。

过去,我设法在IQueryable集合上使用了相同的技术,但我不明白为什么当集合Where上的函数可用IEnumerable并且应该接受我提供的谓词时这不起作用。

非常感谢您的帮助。

4

3 回答 3

5

将您的表达式编译为可执行代码(委托):

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

正如@Kirk 所说,如果您不打算分析它,最好不要使用表达式树。只需使用类型的过滤器Func<Type, bool>

于 2013-06-25T16:10:13.950 回答
3

请注意,Enumerable 扩展方法采用 Func,而不是 Expression。所以你的论点输入错误。

这与实体框架形成对比,实体框架采用 Expression<Func> 而不是普通的 Func。

所以要注意方法签名,它们是相似的,都可以用相同的 lambda 调用,但实际上是不同的!

其背后的原因是 EF 检查 Expression 并将其转换为 SQL 代码,而 Linq to Object 只是在内存中执行谓词。

于 2013-06-25T16:17:26.570 回答
0

你可以试试这个:

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

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

然后你可以自由地改变你的标准过滤器的实现。只要它接受一个 Type 并返回 bool 是否应该包含它,它就会保持模块化并完成我认为你想要的。

于 2013-06-25T16:17:02.307 回答