取消绑定参数

时间:2014-04-06 03:55:46

标签: c# linq expression

所有

我尝试通过表达式树构建动态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);

但系统报告&#34; unding参数c&#34;错误,我该如何解决?

由于

1 个答案:

答案 0 :(得分:0)

虽然filterfilterForExistUser表达式中的参数共享相同的名称,但它们都指的是来自不同范围的不同符号。您的新表达式使用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);
    }
}

密钥是SubstitutionVisitor,用于使用“head”参数替换“tail”参数。

所以你的最终过滤器会变成这样:

Expression<Func<User, bool>> finalFilter =
    CombinePredicates(filter, filterForExistUser);