如果我有一個規範中定義爲表達式如下:規格圖案 - 創建使用的lambda(C#)化合物規格
public Expression<Func<Foo, bool>> IsSuperhuman =
x => x.CanFly && x.HasXRayVision;
我想要定義另一個規範「IsSuperheroine」與邏輯「是超人和是女性',我如何重新使用新規範中的現有規範?
如果我有一個規範中定義爲表達式如下:規格圖案 - 創建使用的lambda(C#)化合物規格
public Expression<Func<Foo, bool>> IsSuperhuman =
x => x.CanFly && x.HasXRayVision;
我想要定義另一個規範「IsSuperheroine」與邏輯「是超人和是女性',我如何重新使用新規範中的現有規範?
你在LinqKit簽出predicate builder嗎?它通過讓你和/或表達式一起建立表達式。
這裏有一個辦法做到這一點:
Expression<Func<Foo, bool>> IsSuperhuman = x => x.CanFly && x.HasXRayVision;
Expression<Func<Foo, bool>> IsSuperheroine = AndAlso(IsSuperhuman, x => x.IsFemale);
...
public static Expression<Func<T, TResult>> AndAlso<T, TResult>(Expression<Func<T, TResult>> expr1, Expression<Func<T, TResult>> expr2)
{
var arg = Expression.Parameter(typeof(T), expr1.Parameters[0].Name);
var andExpr = Expression.AndAlso(
ReplaceParameter(expr1.Body, expr1.Parameters[0], arg),
ReplaceParameter(expr2.Body, expr2.Parameters[0], arg));
return Expression.Lambda<Func<T, TResult>>(andExpr, arg);
}
public static Expression ReplaceParameter(Expression expr, ParameterExpression oldParam, ParameterExpression newParam)
{
return new ReplaceParameterVisitor(oldParam, newParam).Visit(expr);
}
internal class ReplaceParameterVisitor : ExpressionVisitor
{
private ParameterExpression _oldParam;
private ParameterExpression _newParam;
public ReplaceParameterVisitor(ParameterExpression oldParam, ParameterExpression newParam)
{
_oldParam = oldParam;
_newParam = newParam;
}
protected override Expression VisitParameter(ParameterExpression node)
{
if (node == _oldParam)
return _newParam;
return node;
}
}
這可能是不這樣做最簡單的方法,但它的作品...
謝謝!我會直言不諱地說,直到我經歷了Expressions API的這段時間,並找出了它的意義。 – David 2010-08-25 14:07:08
你爲什麼要使用表達式爲這個?看起來代表就夠了。 – leppie 2010-08-20 10:36:01
因爲你不能在IQueryable的Where子句中使用簡單的委託,就像我昨天發現的那樣。 – David 2010-08-20 11:29:06