我有以下代码从程序集中获取类型的集合,其中Type是一个类:
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
我理解我的表达式不符合谓词System.Func<TSource,int,bool>
,但是Where
函数有一个带有System.Func<TSource,bool>
谓词的重载,据我所知应该工作。
我尝试将assembly.GetTypes()
(这是一个数组)的结果以多种方式转换为List,而不会帮助解决问题。
我还确保我已经获得了此课程的所有正确using
语句,因为这似乎是Google搜索过程中遇到的一个问题。
过去我设法在IQueryable
集合上使用了相同的技术,但我不明白为什么当Where
函数在{{1}上可用时这不起作用收集并且应该接受我提供的谓词。
非常感谢您的帮助。
答案 0 :(得分:5)
将表达式编译为可执行代码(委托):
var types = assembly.GetTypes().AsEnumerable().Where(_standardFilter.Compile());
正如@Kirk所说,如果你不打算分析它,最好不要使用表达式树。只需使用Func<Type, bool>
类型的过滤器。
答案 1 :(得分:2)
请注意,Enumerable扩展方法采用Func而不是Expression。所以你的论点输错了。
这与Entity Framework形成对比,后者采用Expression&lt; Func&gt;而不是普通的Func。
所以注意方法签名,它们是相似的,可以用相同的lambda调用,但实际上是不同的!
背后的原因是EF检查Expression并将其转换为SQL代码,而Linq to Object只是在内存中执行谓词。
答案 2 :(得分:0)
您可以尝试这样做:
private Func<Type, bool> standardFilter;
standardFilter = (type) => {
return type.IsClass;
};
var types = assembly.GetTypes().AsEnumerable().Any(x => standardFilter(x));
然后您可以自由更改standardFilter的实现。只要它接收一个Type并返回bool是否应该包含它,它将保持模块化并完成我认为你想要的。