结合表达式树

我有以下表达式:

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

然后我想将此filter应用于几个集合(IQueryable),如下所示:

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

这样做时我收到以下错误:

错误40无法将类型System.Linq.Expressions.Expression<System.Func>隐式转换为bool

我不能使用接口inheritance的解决方法(比如TaskUserinheritance带有int UserId属性的接口(其中T:IHasUserId))因为我想要组合逻辑。

问题是你的UserAccessCheckExpression()方法返回一个ExpressionAny()方法期望一个boolean

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

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

试试这个:

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

更多关于LinqKit

是的,所以,你不能这样做。 Expression<>Func<>之间存在差异。 您正在尝试将UserAccessCheckExpression用作func。 我不确定你要做什么,但是你可以把它编译成一个func,然后像你一样使用它:

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

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