【问题标题】:Combining expression trees组合表达式树
【发布时间】:2016-08-12 16:24:03
【问题描述】:

我有以下表达:

public Expression<Func<T, bool>> UserAccessCheckExpression<T>(int userId) where T : class
{
    return x => (IsAdmin || userId == CurrentUserId || userId == 0);
}

然后我想将此过滤器应用于多个集合(IQueryable),例如:

return tasks
  .Where(t => t.TaskUsers
     .Any(x => UserAccessCheckExpression<TaskUser>(x.User) && x.SomeBool == true));

执行此操作时出现以下错误:

错误 40 无法将类型 System.Linq.Expressions.Expression&lt;System.Func&lt;TaskUser,bool&gt;&gt; 隐式转换为 bool

我不能使用接口继承的解决方法(例如 TaskUser 继承具有 int UserId 属性的接口(其中 T : IHasUserId)),因为我想组合逻辑。

【问题讨论】:

  • 您将不得不手动构建 Lambda,类似于以下内容:stackoverflow.com/questions/4001082/… 我没有足够的时间给出完整的答案。
  • 您将需要使用来自here 的解决方案。然后你会写类似t.TaskUsers.Any(UserAccessCheckExpression)
  • 您的 Linq 提供商是什么?是实体框架吗?你的表情中IsAdminCurrentUserId是什么?
  • @haim770,是英孚。它们是另一个类的属性。
  • @jeroenvanlangen 现在只是一个限制。

标签: c# linq expression iqueryable func


【解决方案1】:

问题是您的UserAccessCheckExpression() 方法返回Expression,而Any() 方法期待boolean

现在,您可以通过编译 Expression 并调用该方法(使用 UserAccessCheckExpression&lt;TaskUser&gt;(x.User).Compile().Invoke(x.User)) 但这显然会在运行时失败,因为 Linq-to-Entities 不会能够将您的 Any() 转换为商店查询,因为它不再包含 Expression

LinqKit 旨在使用它自己的Invoke 扩展方法解决这个问题,在让您的代码编译的同时,将确保您的Expression 将使用另一个名为AsExpandable() 的扩展方法替换回其原始形式那就是扩展实体集。

试试这个:

using LinqKit.Extensions;

return tasks
      .AsExpandable()
      .Where(t => t.TaskUsers.Any(
                       x => UserAccessCheckExpression<TaskUser>(x.User).Invoke(x)
                            && x.SomeBool == true));

More on LinqKit

【讨论】:

  • 出于兴趣,扩展方法是否只编译一次表达式?
  • @Kolky,它在内部调用expr.Compile().Invoke(arg1),但它从未真正被执行。其唯一目的是让Expression在编译时表示为Func,同时确保在运行时使用原始Expression
【解决方案2】:

是的,所以,你不能那样做。 Expression&lt;&gt;Func&lt;&gt; 之间存在差异。您正在尝试使用 UserAccessCheckExpression 作为函数。我不确定您要做什么,但是您可以将其编译为 func,然后像您一样使用它:

var expr = UserAccessCheckExpression<TaskUser>(x.User);
var func = expr.Compile();
// Later use it like ...
var result = func();

但我希望您将它与 EF 或 Linq2Sql 一起使用?在这种情况下,您需要重写表达式。可以手动完成(不容易),或者更好的是使用 PredicateBuilder 之类的工具。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-05
    • 1970-01-01
    相关资源
    最近更新 更多