Cannot cast from generic to get LINQ where clause
OK so I've written the following function:
private IQueryable<LogEntry> SelectAll<T>(IEnumerable<LogEntry> logEntries, List<Expression<Func<LogEntry, bool>>> whereClause)
{
var selectAllQuery = from l in logEntries select l;
if (whereClause != null)
{
foreach (Expression<Func<LogEntry, bool>> whereStatement in whereClause)
{
selectAllQuery = selectAllQuery.Where(whereClause);
}
}
}
But it won't compil开发者_运维技巧e. It throws an error when it tries to return something at "selectAllQuery" as follows:
System.Collections.Generic.IEnumerable' does not contain a definition for 'Where' and the best extension method overload System.Linq.Enumerable.Where(System.Collections.Generic.IEnumerable, System.Func)' has some invalid arguments
I've tried casting this every which way I can think of to no avail. In the above code, running the initial select statement returns selectAllQuery
of type System.Linq.Enumerable.WhereSelectEnumerableIterator<LogEntry,LogEntry>
Clearly I'm missing something fundamental about LINQ. But what?
Cheers.
The problem is that selectAllQuery
is an IEnumerable<LogEntry>
and you need it to be an IQueryable<LogEntry>
in order to use expression trees. Try just changing the first line of the method:
var selectAllQuery = logEntries.AsQueryable();
Alternatively, compile the predicates as you go to get them into delegate form:
foreach (Expression<Func<LogEntry, bool>> whereStatement in whereClause)
{
selectAllQuery = selectAllQuery.Where(whereStatement.Compile());
}
EDIT: Okay, the problems weren't just because of Queryable
, but because of your naming. Let's look at this foreach
statement:
foreach (Expression<Func<LogEntry, bool>> whereStatement in whereClause)
{
selectAllQuery = selectAllQuery.Where(whereClause);
}
You're not using whereStatement
anywhere in the body of the loop. You're trying to call Where
with the entire list of clauses on each iteration. This is where better naming would help. Try this, for example:
private IQueryable<LogEntry> SelectAll<T>(IEnumerable<LogEntry> logEntries,
List<Expression<Func<LogEntry, bool>>> filters)
{
var selectAllQuery = logEntries.AsQueryable();
if (filters != null)
{
foreach (var filter in filters)
{
selectAllQuery = selectAllQuery.Where(filter);
}
}
return selectAllQuery;
}
Because the parameter is now pluralized, it would look obviously wrong as the argument to the Where
method - whereas the difference between whereStatement
and whereClause
isn't at all obvious as the former being singular and the latter being plural.
Some times these kind of errors would get away with simple solution like adding System.Linq to the project...and referring it in the class file. Very sad that VS IDE does not help us to resolve as part of the refactor menu...
精彩评论