Tengo una situación en la que necesito crear dinámicamente una lista de filtros para aplicar a una lista de objetos. Esos objetos pueden ser cualquier cosa que implemente una interfaz que contenga todas las propiedades que necesito filtrar.C# restricción genérica no funciona como se esperaba
public interface IStuff
{
bool SuitableForSomething { get; set; }
bool SuitableForSomethingElse { get; set; }
}
public class SomeStuff : IStuff
{
...
}
public class SomeOtherStuff : IStuff
{
...
}
Tengo una lista de criterios definidos como tal ...
public List<Expression<Func<IStuff, bool>>> Criteria { get; private set; }
y añadir criterios como tal ...
Criteria.Add(x => x.SuitableForSomething);
Criteria.Add(x => x.SuitableForSomethingElse);
I a continuación, aplicar los criterios a mi consulta como tal ...
var stuff= _stuffCache
.GetAll()
.AsQueryable()
.ApplyCriteria(Criteria);
que utiliza el siguiente método de extensión ...
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;
}
El compilador me está diciendo ...
cannot convert from
'System.Linq.Expressions.Expression<System.Func<IStuff,bool>>'
to
'System.Linq.Expressions.Expression<System.Func<T,int,bool>>'
Cuando se ciernen sobre la línea roja bajo el error en el IDE está diciendo que no puede resolver el método entre
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
Si intento convertir la expresión a Expression<Func<T, bool>>
, que debería funcionar ya que T está obligado a implementar la interfaz IStuff. Consigo
Cannot cast expression of type 'Expression<Func<IStuff, bool>>' to type 'Expression<Func<T, bool>>'
EDIT Gracias a la respuesta Raphaël 's He arreglado el método de extensión y, finalmente encontrado el verdadero problema que tenía, que era un problema de fundición cuando me estaba llamando el código. Se arregla fácilmente agregando un .Cast<SomeStuff>()
después de la llamada ApplyCriteria
.
Antes de
var stuff= _stuffCache
.GetAll()
.AsQueryable()
.ApplyCriteria(Criteria);
Después de
var stuff= _stuffCache
.GetAll()
.AsQueryable()
.ApplyCriteria(Criteria)
.Cast<SomeStuff>();
+1 para la respuesta correcta e imaginario +1 para sugerencia de mejora. – SimpleVar
gracias. Ya lo había intentado y obtuve otros errores, que ahora he encontrado una solución. Actualizaré la pregunta con detalles. –