PredicateBuilder返回No Rows

时间:2013-12-10 15:51:21

标签: c# predicatebuilder

此代码正确返回一行:

_loadedAssemblies.ForEach(x =>
{
    foundTypes.AddRange(from t in x.GetTypes()
                        where t.GetInterfaces().Contains(typeof(TInterface))
                     && t.BaseType.Name.LeftOf('`') == baseClass.Name.LeftOf('`')
                        select t);
}

但是,当我使用PredicateBuilder时,我得到零行:

var compiledPredicate = CompiledPredicate<TInterface>();

_loadedAssemblies.ForEach(x =>
{
    foundTypes.AddRange(from t in x.GetTypes()
                        where compiledPredicate.Invoke(typeof(TInterface))
                        select t);
}

    private static Func<Type, bool> CompiledPredicate<T>() where T : class
    {
        // True means all records will be returned if no other predicates are applied.
        var predicate = PredicateBuilder.True<Type>();

        // Get types that implement the interface (T).
        predicate = predicate.And(t => t.GetInterfaces().Contains(typeof(T)));

        // If the config file includes filtering by base class, then filter by it.
        if (!string.IsNullOrWhiteSpace(_baseClass))
        {
            Type baseClass = Type.GetType(_baseClass);
            predicate = predicate.And(t => t.BaseType.Name.LeftOf('`') == baseClass.Name.LeftOf('`'));
        }

        return predicate.Compile();
}

Someone suggested创建我的循环变量的副本,但我试过了,我仍然得到零行。我不确定为什么使用PredicateBuilder不返回任何行。知道我错过了什么吗?

1 个答案:

答案 0 :(得分:1)

您在评论中提到的更改(foundTypes.AddRange(x.GetTypes().AsQueryable().Where(compiledPredicate));)与您使用AsQueryable的事实毫无关系。在第一种情况下,您将硬编码类型传递给谓词的每个调用,在第二种情况下,您将从序列中传递给定项。如果您删除了AsQueryable并使用了Enumerable.Where它也可以使用,或者在调用它时也没有硬编码类型,而是通过了当前项目。

所以你可以这样做:

foundTypes.AddRange(x.GetTypes().Where(compiledPredicate));

此外,在创建谓词时,不需要做你正在做的那么多工作。表达式需要相当多的额外工作才能处理。使用linq到对象,你只需要处理代表,这些代表不那么挑剔。

private static Func<Type, bool> CompiledPredicate<T>() where T : class
{
    Func<Type, bool> predicate = t => t.GetInterfaces().Contains(typeof(T));

    if (!string.IsNullOrWhiteSpace(_baseClass))
    {
        Type baseClass = Type.GetType(_baseClass);
        return t => predicate(t) &&
            t.BaseType.Name.LeftOf('`') == baseClass.Name.LeftOf('`');
    }

    return predicate;
}