最簡單的辦法就是在這裏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);
}
這工作得很好LINQ到對象和LINQ到SQL,但不支持EF。對於EF,你需要使用訪問者來重寫樹,不幸的是。
使用代碼:Combining two lambda expressions in c#
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);
}
還是在.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);
}
該死,剛剛調用內存的工作和EF被測試時發生這種情況。謝謝。 – 2011-03-25 11:00:39
@robert IIRC調用不適用於EF,因此您需要使用第二個版本 – 2011-03-25 11:02:56
您的方法可行,但現在我的代碼庫中有令人驚訝的複雜且未經測試的ReWriter。 :(看到它看起來有多聰明,我會保留它,直到我明白它! – 2011-03-25 11:23:53