2012-11-26 78 views
1

我試圖創建使用表達式,看起來像這樣的可重複使用的方法創建一個表達式:C#表達式 - 從另一種表達

Expression<Func<Order, bool>> CreateExpression(Expression<Func<Order, int>> parameter, FilterOperator operator, int value) 

所以,我可以這樣使用它:

IQueryable<Order> orders = db.Orders; 

var filtered = orders.Where(CreateExpression(o => o.OrderID, FilterOperator.GreaterThan, 100)); 

我不知道如何編寫該方法。我如何編寫一個方法來爲我創建這個表達式?

我需要能夠做這樣的事情:

if(operator == FilterOperator.GreaterThan) 
    return m => m.OrderID > value; 
else if(operator == FilterOperator.LessThan) 
    return m => m.OrderID < value; 

但我想使用在通過直接使用訂單ID,而不是表達。我怎樣才能做到這一點?

+1

那豈不是更容易只是做'orders.Where(o => o.OrderID> 100)'?如果我知道爲什麼這不適合你,我最好提出建議。 –

+0

我不想這樣做,因爲我想要將相同的邏輯應用於OrderID,OrderQuantity等,並且也適用於GreaterThan,LessThan,GreaterThanEqualTo,EqualTo,NotEqualTo等等 – Dismissile

+1

但是lambda表達式非常簡潔,您可以簡單地創建新的與你想要的條件。 –

回答

5
static Expression<Func<T, bool>> CreateExpression<T>(Expression<Func<T, int>> parameter, FilterOperator @operator, int value) 
{ 
    var argExpr = Expression.Parameter(typeof(T), "p"); 
    var paramExpr = Expression.Invoke(parameter, argExpr); 
    var constExpr = Expression.Constant(value); 
    Expression compExpr = null; 
    switch(@operator) 
    { 
     case FilterOperator.GreaterThan: 
      compExpr = Expression.GreaterThan(paramExpr, constExpr); 
      break; 
     case FilterOperator.LessThan: 
      compExpr = Expression.LessThan(paramExpr, constExpr); 
      break; 
    } 

    return Expression.Lambda<Func<T, bool>>(compExpr, argExpr); 
} 

如果您不能使用Invoke和你parameter表達是一個成員表達,那麼你可以使用新的參數重新創建它:

static Expression<Func<T, bool>> CreateExpression<T>(Expression<Func<T, int>> parameter, FilterOperator @operator, int value) 
{ 
    var memberExpr = (MemberExpression)parameter.Body; 
    PropertyInfo property = (PropertyInfo)memberExpr.Member; 

    var argExpr = Expression.Parameter(typeof(T), "p"); 
    var propertyExpr = Expression.Property(argExpr, property); 
    var constExpr = Expression.Constant(value); 

    Expression compExpr = null; 
    switch(@operator) 
    { 
     case FilterOperator.GreaterThan: 
      compExpr = Expression.GreaterThan(propertyExpr, constExpr); 
      break; 
     case FilterOperator.LessThan: 
      compExpr = Expression.LessThan(propertyExpr, constExpr); 
      break; 
    } 

    return Expression.Lambda<Func<T, bool>>(compExpr, argExpr); 
} 
+0

我正在使用它一個IQueryable,並得到一個錯誤,Invoke不被支持。有沒有其他的選擇? – Dismissile

+0

@Dismissile - 如果你的'parameter'表達式是一個屬性訪問器,那麼是的。我會在一分鐘內更新... – Lee

+0

是的,它是一個POCO的財產。 – Dismissile