组合表达式树
Combining expression trees
我有以下表达式:
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));
我在执行此操作时遇到以下错误:
Error 40 Cannot implicitly convert type System.Linq.Expressions.Expression<System.Func<TaskUser,bool>>
to bool
我不能使用带有接口继承的解决方法(比如 TaskUser 继承带有 int UserId 属性 的接口(其中 T : IHasUserId)),因为我想组合逻辑。
问题是您的 UserAccessCheckExpression()
方法返回 Expression
而 Any()
方法期望返回 boolean
.
现在,您可以通过编译 Expression
并调用方法(使用 UserAccessCheckExpression<TaskUser>(x.User).Compile().Invoke(x.User))
但这显然会在运行时失败,从而使您的代码 compile因为 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));
是的,所以,你不能那样做。 Expression<>
和 Func<>
是有区别的。您正在尝试将 UserAccessCheckExpression
用作函数。我不确定你想做什么,但你可以将它编译成一个函数,然后像你这样使用它:
var expr = UserAccessCheckExpression<TaskUser>(x.User);
var func = expr.Compile();
// Later use it like ...
var result = func();
但我希望您将其与 EF 或 Linq2Sql 一起使用?在这种情况下,您需要重写表达式。它可以手动完成(不容易),或者更好的是,使用像 PredicateBuilder 这样的工具。
我有以下表达式:
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));
我在执行此操作时遇到以下错误:
Error 40 Cannot implicitly convert type
System.Linq.Expressions.Expression<System.Func<TaskUser,bool>>
tobool
我不能使用带有接口继承的解决方法(比如 TaskUser 继承带有 int UserId 属性 的接口(其中 T : IHasUserId)),因为我想组合逻辑。
问题是您的 UserAccessCheckExpression()
方法返回 Expression
而 Any()
方法期望返回 boolean
.
现在,您可以通过编译 Expression
并调用方法(使用 UserAccessCheckExpression<TaskUser>(x.User).Compile().Invoke(x.User))
但这显然会在运行时失败,从而使您的代码 compile因为 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));
是的,所以,你不能那样做。 Expression<>
和 Func<>
是有区别的。您正在尝试将 UserAccessCheckExpression
用作函数。我不确定你想做什么,但你可以将它编译成一个函数,然后像你这样使用它:
var expr = UserAccessCheckExpression<TaskUser>(x.User);
var func = expr.Compile();
// Later use it like ...
var result = func();
但我希望您将其与 EF 或 Linq2Sql 一起使用?在这种情况下,您需要重写表达式。它可以手动完成(不容易),或者更好的是,使用像 PredicateBuilder 这样的工具。