为什么此筛选器适用于 List<T> 但不适用于 IQueryable<T>?

Why does this filter work on a List<T> but not on an IQueryable<T>?

我需要创建一个扩展方法来根据验证规则列表 List<<IRule>, bool> 过滤集合 List<TSource>。 但是我得到一个错误 VisitSubQueryExpression method is not implemented 而我没有 see/can 找不到问题的原因。

这是我的扩展方法:

public static List<TSource> ValidItems<TSource>(this IQueryable<TSource> source, 
                                  List<IValidationRule<TSource>> validationRules)
{
     return source.Where(testableItem => 
            validationRules.All(rule => rule.RulePassed(testableItem))).ToList();
}

IRule 接口:

public interface IValidationRule<T> //with implementation class ValidationRule<T>
{
    Func<T, bool> RulePassed { get; set; }
    //... +other code
}

扩展方法调用示例[​​=46=]

//initialization of List<SampleType> listToValidate = ... 
var validItems = listToValidate.ValidItems(
                  new List<IValidationRule<SampleType>() {
                       new ValidationType<SampleType> {
                       RulePassed = (s) => string.IsNullOrWhiteSpace(SampleType.Name), 
                       //...initalize other ValidationType parameters
                       }
                   });

此示例应过滤 listToValidate 列表并删除所有 SampleType 实例,名称 属性 为 Null 或 Whitespace

我的扩展方法有什么问题?这个 "VisitSubQueryExpression method is not implemented" 错误是什么意思?

如果我将其更改为 List<TSource> 而不是 IQueryable<TSource> 的扩展方法 - 它有效!为什么?

this IQueryable<TSource>替换为this List<TSource>,有效,为什么? Where 方法应该适用于 IQueryable<T>(继承自 IEnumerable<T>),不是吗?

public static List<TSource> ValidItems<TSource>(this List<TSource> source, 
                                  List<IValidationRule<TSource>> validationRules)
{
     return source.Where(testableItem => 
            validationRules.All(rule => rule.RulePassed(testableItem))).ToList();
}

List<T> 没有实现 IQueryable<T>,所以你不能调用在 IQueryable<T>.

上定义的扩展方法

您的 rule.RulePassed 无法由您的 IQueryable 提供商翻译。

public static List<TSource> ValidItems<TSource>(this IQueryable<TSource> source, 
                              List<IValidationRule<TSource>> validationRules)
{
    var result = new List<TSource>();
    foreach (var testableItem in source)
    {
        if (validationRules.All(rule => rule.RulePassed(testableItem))
        {
            result.Add(testableItem);
        }
    }
    return result;
}

IQueryable<T> 实现了 IEnumerable<T> 但反之则不然。 List<T> 没有实现 IQueryable<T>.

这是List公开的接口列表:

由于 IQueryableIList 都继承自 IEnumerable<T>,您可以使用它并调用 .AsQueryable 来转换这两种情况。