2012-11-26 53 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