all
我尝试通过表达式树构建动态 linq 查询,下面是我的代码
Expression<Func<User, bool>> filter = c => c.isAdmin == false;
Expression<Func<User, bool>> filterForExistUser = c => (c.isfreezed == null ? false : c.isfreezed) != true;
Expression<Func<User, bool>> finalFilter = Expression.Lambda<Func<User, bool>>(Expression.AndAlso(filter.Body, filterForExistUser.Body), filter.Parameters);
IQueryable<User> myusers = db.Users.AsQueryable<User>();
MethodCallExpression whereCallExpression = Expression.Call(
typeof(Queryable),
"Where",
new Type[] { myusers.ElementType },
myusers.Expression,
finalFilter);
IQueryable<User> results = myusers.Provider.CreateQuery<User>(whereCallExpression);
foreach (User user in results)
Console.WriteLine(user.UserName);
但是系统报告"unding参数c"错误,我该如何解决?
谢谢
尽管 filter
和 filterForExistUser
表达式中的参数共享相同的名称,但它们都引用来自不同作用域的不同符号。 新表达式使用filter
表达式中的参数,但省略了filterForExistUser
的参数。 必须重写表达式,以便在整个表达式中使用相同的单个参数。
下面是可用于组合谓词的通用方法:
Expression<Func<TSource, bool>> CombinePredicates<TSource>(
Expression<Func<TSource, bool>> head,
params Expression<Func<TSource, bool>>[] tail)
{
var param = head.Parameters.Single();
var body = tail.Aggregate(
head.Body,
(result, expr) => Expression.AndAlso(result,
new SubstitutionVisitor
{
OldExpr = expr.Parameters.Single(),
NewExpr = param,
}.Visit(expr.Body)
)
);
return Expression.Lambda<Func<TSource, bool>>(body, param);
}
public class SubstitutionVisitor : ExpressionVisitor
{
public Expression OldExpr { get; set; }
public Expression NewExpr { get; set; }
public override Expression Visit(Expression node)
{
return (node == OldExpr) ? NewExpr : base.Visit(node);
}
}
关键是用于使用 "head" 参数替换 "tail" 参数的 SubstitutionVisitor
。
所以你的最终过滤器变成这样:
Expression<Func<User, bool>> finalFilter =
CombinePredicates(filter, filterForExistUser);