I have a situation where I need to dynamically build up a list of filters to apply to a list of objects. Those objects can be anything that implements an interface which contains all of the properties I need to filter on.
public interface IStuff
{
bool SuitableForSomething { get; set; }
bool SuitableForSomethingElse { get; set; }
}
public class SomeStuff : IStuff
{
...
}
public class SomeOtherStuff : IStuff
{
...
}
I have a list of criteria defined like so ...
public List<Expression<Func<IStuff, bool>>> Criteria { get; private set; }
and add criteria like so ...
Criteria.Add(x => x.SuitableForSomething);
Criteria.Add(x => x.SuitableForSomethingElse);
I then apply the criteria to my query like so ...
var stuff= _stuffCache
.GetAll()
.AsQueryable()
.ApplyCriteria(Criteria);
which uses the following extension method ...
public static IQueryable<T> ApplyCriteria<T>(this IQueryable<T> stuff, List<Expression<Func<IStuff, bool>>> criteria)
where T : IStuff
{
foreach (var expression in criteria)
{
stuff = Queryable.Where(stuff, expression);
}
return stuff;
}
The compiler is telling me ...
cannot convert from
'System.Linq.Expressions.Expression<System.Func<IStuff,bool>>'
to
'System.Linq.Expressions.Expression<System.Func<T,int,bool>>'
When I hover over the red line under the error in the IDE it's saying it cannot resolve method between
IQueryable<IStuff> Where<IStuff>(this IQueryable<IStuff>, Expression<Func<IStuff, bool>>) in class Queryable
and
IQueryable<T> Where<T>(this IQueryable<T>, Expression<Func<T,int,bool>>) in class Queryable
If I try casting the expression to Expression<Func<T, bool>>
, which ought to work as T is constrained to implement the IStuff interface. I get
Cannot cast expression of type 'Expression<Func<IStuff, bool>>' to type 'Expression<Func<T, bool>>'
EDIT
Thanks to Raphaël's answer I fixed the extension method and eventually found the real problem I had, which was a casting problem when I was calling the code. Easily fixed by adding a .Cast<SomeStuff>()
after the ApplyCriteria
call.
Before
var stuff= _stuffCache
.GetAll()
.AsQueryable()
.ApplyCriteria(Criteria);
After
var stuff= _stuffCache
.GetAll()
.AsQueryable()
.ApplyCriteria(Criteria)
.Cast<SomeStuff>();