Rob*_*all 11 c# linq expression-trees
我正在尝试基于Specification对象动态构建表达式.
我创建了一个ExpressionHelper类,它有一个私有表达式,如下所示:
private Expression<Func<T, bool>> expression;
public ExpressionHelper()
{
expression = (Expression<Func<T, bool>>)(a => true);
}
Run Code Online (Sandbox Code Playgroud)
然后一些简单的方法如下:
public void And(Expression<Func<T,bool>> exp);
Run Code Online (Sandbox Code Playgroud)
我正在和And方法的身体挣扎.我基本上想要撕掉身体exp,用那些参数替换所有参数expression然后将它附加到expression身体的末端和AndAlso.
我这样做了:
var newBody = Expression.And(expression.Body,exp.Body);
expression = expression.Update(newBody, expression.Parameters);
Run Code Online (Sandbox Code Playgroud)
但最终我的表达看起来像这样:
{ a => e.IsActive && e.IsManaged }
Run Code Online (Sandbox Code Playgroud)
有更简单的方法吗?或者我怎样才能撕掉那些e并用一个替换它们?
Mar*_*ell 21
这里最简单的方法是Expression.Invoke,例如:
public static Expression<Func<T, bool>> AndAlso<T>(
Expression<Func<T, bool>> x, Expression<Func<T, bool>> y)
{
return Expression.Lambda<Func<T, bool>>(
Expression.AndAlso(x.Body, Expression.Invoke(y, x.Parameters)),
x.Parameters);
}
Run Code Online (Sandbox Code Playgroud)
这适用于LINQ-to-Objects和LINQ-to-SQL,但不支持EF.对于EF,你可能需要使用访问者重写树,遗憾的是.
使用以下代码:在c#中组合两个lambda表达式
public static Expression<Func<T, bool>> AndAlso<T>(
Expression<Func<T, bool>> x, Expression<Func<T, bool>> y)
{
var newY = new ExpressionRewriter().Subst(y.Parameters[0], x.Parameters[0]).Inline().Apply(y.Body);
return Expression.Lambda<Func<T, bool>>(
Expression.AndAlso(x.Body, newY),
x.Parameters);
}
Run Code Online (Sandbox Code Playgroud)
或者在.NET 4.0中,使用ExpressionVisitor:
class ParameterVisitor : ExpressionVisitor
{
private readonly ReadOnlyCollection<ParameterExpression> from, to;
public ParameterVisitor(
ReadOnlyCollection<ParameterExpression> from,
ReadOnlyCollection<ParameterExpression> to)
{
if(from == null) throw new ArgumentNullException("from");
if(to == null) throw new ArgumentNullException("to");
if(from.Count != to.Count) throw new InvalidOperationException(
"Parameter lengths must match");
this.from = from;
this.to = to;
}
protected override Expression VisitParameter(ParameterExpression node)
{
for (int i = 0; i < from.Count; i++)
{
if (node == from[i]) return to[i];
}
return node;
}
}
public static Expression<Func<T, bool>> AndAlso<T>(
Expression<Func<T, bool>> x, Expression<Func<T, bool>> y)
{
var newY = new ParameterVisitor(y.Parameters, x.Parameters)
.VisitAndConvert(y.Body, "AndAlso");
return Expression.Lambda<Func<T, bool>>(
Expression.AndAlso(x.Body, newY),
x.Parameters);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4077 次 |
| 最近记录: |