【问题标题】:How to use an expression with a generic func lambda in a linq where clause?如何在 linq where 子句中使用带有通用 func lambda 的表达式?
【发布时间】:2011-10-21 11:54:10
【问题描述】:

这就是我所拥有的

private readonly Dictionary<Type, List<object>> _cache;

public IList<T> Get<T> (Expression<Func<T, bool>> criteria)
{
    return _cache[typeof(T)].Where (criteria);
}

编译器抱怨(正确地)它不能从对象转换为 T。

我应该如何从那里着手?


解决方案

return _cached[type].AsQueryable().Cast<T>().Where (criteria).ToList()

我们的想法是将 List 作为 IQueryable,然后我可以投射...

【问题讨论】:

    标签: c# linq lambda expression-trees


    【解决方案1】:

    使用.Cast&lt;&gt;() Extension Method

    private readonly Dictionary<Type, List<object>> _cache;
    
    public IList<T> Get<T> (Expression<Func<T, bool>> criteria)
    {
        return _cache[typeof(T)].Cast<T>().Where (criteria).ToList();
    }
    

    如果您不能绝对确定所有元素都是 T 类型,则可以改用 .OfType&lt;T&gt;()(它会跳过无法转换的元素)

    编辑当 T 是值类型(结构)时,您还需要使用.OfType&lt;T&gt;()

    编辑由于您的评论提到了 IQueryable,这可能会有所帮助:

    return _cache[typeof(T)].AsQueryable().Cast<T>().Where (criteria).ToList();
    

    【讨论】:

    • @Stécy 你能...显示错误的代码吗?一定有别的事情发生了
    • @Stécy: 直到你在方法声明中添加where T : class 才能真正做到
    • 'System.Collections.Generic.IEnumerable' 不包含 'Where' 的定义和最佳扩展方法重载 'System.Linq.Queryable.Where(System.Linq .IQueryable, System.Linq.Expressions.Expression>)' 有一些无效参数
    • @Stécy: using System.Linq; 应该对您有帮助除了List&lt;object&gt; 之外,您的字典中还有其他内容? (列表不是 IQueryable)
    • 将已确认的解决方案添加到答案中以供将来参考
    【解决方案2】:
    private readonly Dictionary<Type, List<object>> _cache;
    
    public IList<T> Get<T> (Expression<Func<T, bool>> criteria)
    {
        return _cache[typeof(T)].Cast<T>().Where(criteria).ToList();
    }
    

    【讨论】:

    • 给出以下错误:'System.Collections.Generic.IEnumerable'不包含'Where'的定义和最佳扩展方法重载'System.Linq.Queryable.Where(System.Linq.IQueryable, System.Linq.Expressions.Expression>)' 有一些无效参数
    • 您的回答将我引向正确的方向。我只在演员表之前添加了 AsQueryable() 并且编译器现在很高兴。
    • 如果您包含 System.Linq,该错误应该会消失。这是因为在不同的命名空间中有不同的扩展方法,具体取决于您是在 IQueryable 还是 IEnumerable 上操作。
    【解决方案3】:

    好的,修复它:

    return _cached[type].AsQueryable().Cast<T>().Where (criteria).ToList()
    

    我们的想法是将 List 作为 IQueryable,然后我可以投射...

    【讨论】:

      【解决方案4】:

      可能是动态构建表达式然后编译它是一个更好的选择。这是一个示例:

      Expression<Func<TestClass, bool>> query = LambdaBuilder.BuildQuery(queryItems);
      Func<TestClass, bool> compiledExpression = query.Compile();
      var results = data.Where(compiledExpression);
      

      你可以在上面阅读my article

      【讨论】:

        【解决方案5】:

        你真的需要参数是 Expression> 吗?当然,这应该可以解决问题:

        private readonly Dictionary<Type, List<object>> _cache;
        
        public IList<T> Get<T>(Func<T,bool> criteria)
        {
            return _cache[typeof(T)].Cast<T>().Where(criteria).ToList();
        }
        

        【讨论】:

          猜你喜欢
          • 2021-11-10
          • 2014-02-01
          • 1970-01-01
          • 2010-11-06
          • 1970-01-01
          • 2023-03-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多