C# 泛型约束未按预期工作
本文关键字:工作 泛型 约束 | 更新日期: 2023-09-27 18:37:04
>我遇到一种情况,我需要动态构建一个过滤器列表以应用于对象列表。这些对象可以是实现接口的任何对象,该接口包含我需要过滤的所有属性。
public interface IStuff
{
bool SuitableForSomething { get; set; }
bool SuitableForSomethingElse { get; set; }
}
public class SomeStuff : IStuff
{
...
}
public class SomeOtherStuff : IStuff
{
...
}
我有一个定义的标准列表,如下所示...
public List<Expression<Func<IStuff, bool>>> Criteria { get; private set; }
并添加这样的标准...
Criteria.Add(x => x.SuitableForSomething);
Criteria.Add(x => x.SuitableForSomethingElse);
然后,我将条件应用于我的查询,如下所示...
var stuff= _stuffCache
.GetAll()
.AsQueryable()
.ApplyCriteria(Criteria);
它使用以下扩展方法...
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;
}
编译器告诉我...
cannot convert from
'System.Linq.Expressions.Expression<System.Func<IStuff,bool>>'
to
'System.Linq.Expressions.Expression<System.Func<T,int,bool>>'
当我将鼠标悬停在IDE错误下的红线上时,它说它无法解析
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
如果我尝试将表达式转换为 Expression<Func<T, bool>>
,它应该工作,因为 T 被约束来实现 IStuff 接口。我得到
Cannot cast expression of type 'Expression<Func<IStuff, bool>>' to type 'Expression<Func<T, bool>>'
编辑感谢Raphaël的回答,我修复了扩展方法,并最终找到了我遇到的真正问题,这是我调用代码时的转换问题。通过在ApplyCriteria
呼叫后添加.Cast<SomeStuff>()
轻松修复。
以前
var stuff= _stuffCache
.GetAll()
.AsQueryable()
.ApplyCriteria(Criteria);
后
var stuff= _stuffCache
.GetAll()
.AsQueryable()
.ApplyCriteria(Criteria)
.Cast<SomeStuff>();
将第二个参数类型更改为List<Expression<Func<T,bool>>>
(T 而不是 IStuff)
public static IQueryable<T> ApplyCriteria<T>(this IQueryable<T> stuff, List<Expression<Func<T, bool>>> criteria)
where T : IStuff
{
foreach (var expression in criteria)
{
stuff = Queryable.Where(stuff, expression);
//or stuff = stuff.Where(expression), as Where is an Extension method;
}
return stuff;
}
并且您的方法可以(Thx Resharper),重写为
public static IQueryable<T> ApplyCriteria<T>(this IQueryable<T> stuff, List<Expression<Func<T, bool>>> criteria)
where T : IStuff
{
return criteria.Aggregate(stuff, (current, expression) => current.Where(expression));
}