如何使用表达式(Of TDelegate).更新方法
本文关键字:更新 新方法 TDelegate Of 何使用 表达式 | 更新日期: 2023-09-27 18:15:32
我已经使用Lambda表达式构建了一个存储库来过滤我的实体集合。作为方法的参数,我将发送Expression<Func<Case, bool>> exp
。但在方法内部,我想用一些全局过滤器更新相同的表达式。我可以看到表达式对象本身有一个Update方法,但我不知道它是如何实现的(在搜索网络时找不到任何东西(。
exp.Update(exp.Body, ???);
有人能举个例子吗??
编辑:方法的定义:http://msdn.microsoft.com/en-us/library/ee378255.aspx
第二版:这是我的代码(我尝试使用的地方(:
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();
它失败,出现以下ArgumentException:Lambda类型参数必须从System.Delegate 派生
我认为Update
方法对您没有帮助。它只创建一个新的lambda,但不会用新的参数更新原始参数,您必须手动执行。我建议使用一个访问者来替换参数,然后可以将表达式And
放在一起。
总的来说,你会得到这样的东西:
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);
}
}
System.Linq.Expressions.Expression.And(exp.Body, newExpression.Body);
示例:
Expression<Func<int, bool>> f = p => true;
var a = Expression.And(f.Body, f.Body);
ParameterExpression pParam = Expression.Parameter(typeof(int), "p");
var b = (new int[] { 1, 2, 3 }).Where(Expression.Lambda<Func<int, bool>>(a,
new ParameterExpression[] { pParam }).Compile());