C# PredicateBuilder不返回任何行

C# PredicateBuilder不返回任何行,c#,predicatebuilder,C#,Predicatebuilder,此代码正确返回一行: _loadedAssemblies.ForEach(x => { foundTypes.AddRange(from t in x.GetTypes() where t.GetInterfaces().Contains(typeof(TInterface)) && t.BaseType.Name.LeftOf('`') == baseClass.Name.L

此代码正确返回一行:

_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();
}
var compiledPredicate=compiledPredicate();
_loadedAssemblies.ForEach(x=>
{
foundTypes.AddRange(从x.GetTypes()中的t开始)
其中compiledPredicate.Invoke(typeof(TInterface))
选择t);
}
私有静态Func CompiledPredicate(),其中T:class
{
//True表示如果没有应用其他谓词,则将返回所有记录。
var predicate=PredicateBuilder.True();
//获取实现接口(T)的类型。
predicate=predicate.And(t=>t.GetInterfaces().Contains(typeof(t));
//如果配置文件包括按基类过滤,则按基类过滤。
如果(!string.IsNullOrWhiteSpace(_baseClass))
{
Type baseClass=Type.GetType(_baseClass);
predicate=predicate.And(t=>t.BaseType.Name.LeftOf('`')==baseClass.Name.LeftOf('`');
}
返回谓词Compile();
}

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

您在注释中提到的更改(
foundTypes.AddRange(x.GetTypes().AsQueryable().Where(compiledPredicate));
)与您使用的是
AsQueryable
这一事实毫无关系。在第一种情况下,您向谓词的每个调用传递一个硬编码类型,在第二种情况下,您从序列中传递给定的项。您是否删除了
AsQueryable
并使用了
Enumerable。在哪里
它也可以工作,或者在调用当前项时传递了当前项,而不是硬编码类型,该类型也可以工作

因此,您可以简单地执行以下操作:

foundTypes.AddRange(x.GetTypes().Where(compiledPredicate));
另外,在创建谓词时,不需要像您现在这样做。表达式需要处理相当多的额外工作。使用linq to对象,您只需要处理委托,这就不那么挑剔了

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;
}
private static Func CompiledPredicate(),其中T:class
{
Func predicate=t=>t.GetInterfaces()包含(typeof(t));
如果(!string.IsNullOrWhiteSpace(_baseClass))
{
Type baseClass=Type.GetType(_baseClass);
返回t=>谓词(t)&&
t、 BaseType.Name.LeftOf('`')==baseClass.Name.LeftOf('`');
}
返回谓词;
}

您在注释中提到的更改(
foundTypes.AddRange(x.GetTypes().AsQueryable().Where(compiledPredicate));
)与您使用的是
AsQueryable
这一事实毫无关系。在第一种情况下,您向谓词的每个调用传递一个硬编码类型,在第二种情况下,您从序列中传递给定的项。您是否删除了
AsQueryable
并使用了
Enumerable。在哪里
它也可以工作,或者在调用当前项时传递了当前项,而不是硬编码类型,该类型也可以工作

因此,您可以简单地执行以下操作:

foundTypes.AddRange(x.GetTypes().Where(compiledPredicate));
另外,在创建谓词时,不需要像您现在这样做。表达式需要处理相当多的额外工作。使用linq to对象,您只需要处理委托,这就不那么挑剔了

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;
}
private static Func CompiledPredicate(),其中T:class
{
Func predicate=t=>t.GetInterfaces()包含(typeof(t));
如果(!string.IsNullOrWhiteSpace(_baseClass))
{
Type baseClass=Type.GetType(_baseClass);
返回t=>谓词(t)&&
t、 BaseType.Name.LeftOf('`')==baseClass.Name.LeftOf('`');
}
返回谓词;
}

如果使用linq to objects,为什么要使用
PredicateBuilder
呢?它实际上只对处理表达式有用。@Servy,因为我不太清楚。使用linq to objects就是问题所在吗?使用linq to objects有简单得多的方法。你用大锤敲钉子。好的,很好我不知道为什么,但这样做是有效的:
foundTypes.AddRange(x.GetTypes().AsQueryable().Where(compiledPredicate))
如果您使用linq to objects,为什么要使用
PredicateBuilder
呢?它实际上只对处理表达式有用。@Servy,因为我不太清楚。使用linq to objects会有问题吗?使用linq to objects有简单得多的方法。您使用的是大锤敲打钉子。好的,很好知道。那么什么是更好的方法呢?我不知道为什么,但这样做是有效的:
foundTypes.AddRange(x.GetTypes().AsQueryable().Where(compiledPredicate));
FYI:新代码在这里生成堆栈溢出异常:
predicate=t=>predicate(t)&&
@BobHorn Right,修复。没有注意到。仅供参考:新代码在此处生成堆栈溢出异常:
predicate=t=>predicate(t)&&
@BobHorn Right,修复。没有注意到。