2

I have the following code to get a collection of Types from an Assembly where the Type is a Class:

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

This works fine and as expected. However I wanted to pull out the lambda expression to a Linq Expression variable (as later on it will be used in a parameter of this method). So I did the following:

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

However this won't compile with the error:

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

I understand that my expression doesn't conform to the predicate System.Func<TSource,int,bool>, however the Where function has an overload that takes a predicate of System.Func<TSource,bool>, which as far as I can tell should work.

I have tried converting the result of assembly.GetTypes() (which is an array) to a List in several ways without it helping the issue.

I have also made sure that I have got all the correct using statements for this class as that seems to be an issue several people run into during my Googling.

In the past I have managed to use this same technique on a IQueryable collection, but I don't understand why this won't work when the Where function is available on the IEnumerable collection and should accept the predicate I am providing.

Thanks very much for any assistance.

3
  • 1
    Expression<Func<...>> and Func<...> are not the same things. Commented Jun 25, 2013 at 16:11
  • The Where extension method on IQueryable<T> accepts an Expression<Func<T, bool>>, which is why you've been able to do it before. This is what allows things like EF to pass in an expression and compile it later. But on IEnumerable<T>, it only accepts <Func<T, bool>>. Commented Jun 25, 2013 at 16:15
  • So yet again it boils down to me not noticing one specific word! I really should step back at times and pay a bit more attention to the things I have assumed! Commented Jun 26, 2013 at 18:41

3 Answers 3

5

Compile your expression into executable code (delegate):

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

As @Kirk stated, it's better not to use expression tree, if you are not going to analyze it. Simply use filter of type Func<Type, bool>.

Sign up to request clarification or add additional context in comments.

2 Comments

Or even better, don't wrap the lambda in an expression tree in the first place.
@KirkWoll completely agree with you :)
3

Note that the Enumerable extension method takes a Func, not an Expression. So your argument is incorrectly typed.

This is in contrast with Entity Framework, which takes Expression<Func> rather than plain Func.

So be attentive to method signatures, they are similar, can both be called with the same lambda, but are actually different!

The reason behind that is that EF inspects the Expression and converts it to SQL code, whereas Linq to Object simply executes the predicate in memory.

Comments

0

You could try this instead:

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

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

Then you're free to change your implementation of standardFilter. As long as it takes in a Type and returns bool for whether or not that should be included it will remain modular and accomplish what I think you're going for.

1 Comment

Or simply private Func<Type, bool> standardFilter = type => type.IsClass; var types = assembly.GetTypes().AsEnumerable().Any(standardFilter);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.