【问题标题】:PredicateBuilder Returns No RowsPredicateBuilder 不返回任何行
【发布时间】:2013-12-11 22:40:54
【问题描述】:

此代码正确返回一行:

_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 不会返回任何行。知道我缺少什么吗?

【问题讨论】:

  • 如果您使用 linq to objects,为什么还要使用 PredicateBuilder?它真的只对处理表达式有用。
  • @Servy 因为我不知道更好。使用 linq 来对象是这里的问题吗?
  • 在使用 linq to objects 时有更简单的方法。你在用大锤敲钉子。
  • 好的,很高兴知道。那么有什么更好的方法呢?
  • 我不知道为什么,但这样做很有效:foundTypes.AddRange(x.GetTypes().AsQueryable().Where(compiledPredicate));

标签: c# predicatebuilder


【解决方案1】:

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

所以你可以简单地做:

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;
}

【讨论】:

  • 仅供参考:新代码在此处产生堆栈溢出异常:predicate = t =&gt; predicate(t) &amp;&amp;
  • @BobHorn 对,已修复。没注意到。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-04
  • 1970-01-01
  • 2015-06-13
  • 2018-10-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多