The change that you mentioned in comments (foundTypes.AddRange(x.GetTypes().AsQueryable().Where(compiledPredicate));
) had nothing at all to do with the fact that you were using AsQueryable
. In the first case you're passing in a hard coded type to each call of your predicate, in the second you're passing the given item from the sequence. Had you removed the AsQueryable
and used Enumerable.Where
it would also work, or had you passed the current item, rather than a hard coded type, when invoking it that would also work.
So you can simply do:
foundTypes.AddRange(x.GetTypes().Where(compiledPredicate));
Also, when creating the predicate, there's no need to do as much work as you're doing. Expressions take a fair amount of extra work to deal with. With linq to objects you only need to deal with delegates, which are much less finicky.
private static Func<Type, bool> CompiledPredicate<T>() where T : class
{
Func<Type, bool> predicate = t => t.GetInterfaces().Contains(typeof(T));
if (!string.IsNullOrWhiteSpace(_baseClass))
{
Type baseClass = Type.GetType(_baseClass);
return t => predicate(t) &&
t.BaseType.Name.LeftOf('`') == baseClass.Name.LeftOf('`');
}
return predicate;
}