如何使用Expression(Of TDelegate).Update方法

bad*_*ddy 5 c# lambda expression

我使用Lambda表达式构建了一个存储库来过滤我的实体集合.作为我发送的方法的参数Expression<Func<Case, bool>> exp.但是在方法中我想用一些全局过滤器更新同一个表达式.我可以看到表达式对象本身有一个Update方法,但我无法弄清楚它是如何实现的(在搜索网络时找不到任何东西).

exp.Update(exp.Body, ???);
Run Code Online (Sandbox Code Playgroud)

谁能举个例子?

编辑:方法的定义:http://msdn.microsoft.com/en-us/library/ee378255.aspx

EDIT2:这是我的代码(我尝试使用.And):

Expression<Func<Case, bool>> newExp = c => c.CaseStatusId != (int)CaseStatus.Finished
var binExp = Expression.And(exp.Body, newExp.Body);
ParameterExpression paramExp = Expression.Parameter(typeof(Expression<Func<Case, bool>>), "c");
return repository.Where(Expression.Lambda<Expression<Func<Case, bool>>>(binExp, 
    new[] { paramExp }).Compile()).ToArray();
Run Code Online (Sandbox Code Playgroud)

它失败并出现以下ArgumentException:Lambda类型参数必须从System.Delegate派生

MBo*_*ros 9

我不认为Update方法可以帮助你.它onlu创建一个新的lambda,但不用新的参数更新原始参数,你必须手动完成.我建议有一个访问者替换参数,然后你可以和表达式一起.

你会得到类似的东西:

    private Case[] getItems(Expression<Func<Case, bool>> exp)
    {
        return repository.Where(AddGlobalFilters(exp).Compile()).ToArray();
    }

    private Expression<Func<Case, bool>> AddGlobalFilters(Expression<Func<Case, bool>> exp)
    {
        // get the global filter
        Expression<Func<Case, bool>> newExp = c => c.CaseStatusId != (int)CaseStatus.Finished;

        // get the visitor
        var visitor = new ParameterUpdateVisitor(newExp.Parameters.First(), exp.Parameters.First());
        // replace the parameter in the expression just created
        newExp = visitor.Visit(newExp) as Expression<Func<Case, bool>>;

        // now you can and together the two expressions
        var binExp = Expression.And(exp.Body, newExp.Body);
        // and return a new lambda, that will do what you want. NOTE that the binExp has reference only to te newExp.Parameters[0] (there is only 1) parameter, and no other
        return Expression.Lambda<Func<Case, bool>>(binExp, newExp.Parameters);
    }


    /// <summary>
    /// updates the parameter in the expression
    /// </summary>
    class ParameterUpdateVisitor : ExpressionVisitor
    {
        private ParameterExpression _oldParameter;
        private ParameterExpression _newParameter;

        public ParameterUpdateVisitor(ParameterExpression oldParameter, ParameterExpression newParameter)
        {
            _oldParameter = oldParameter;
            _newParameter = newParameter;
        }

        protected override Expression VisitParameter(ParameterExpression node)
        {
            if (object.ReferenceEquals(node, _oldParameter))
                return _newParameter;

            return base.VisitParameter(node);
        }
    }
Run Code Online (Sandbox Code Playgroud)