2010-09-17 8 views
1

J'ai une méthode pour ajouter une condition de date à ma requête linq. Ce que je veux faire, c'est passer x.Due en paramètre pour que cela fonctionne avec n'importe quelle date. Des idées?Comment puis-je extraire le chemin membre de cette expression lambda

protected virtual IQueryable<TaskView> AddTaskDuePredicate(DateCriteria dateCriterion, IQueryable<TaskView> taskSummary) 
{ 
     if (dateCriterion.Condition == DateCondition.LessThan) 
      taskSummary = taskSummary.Where(x => x.Due < dateCriterion.Value1); 
     else if (dateCriterion.Condition == DateCondition.LessThanOrEqualTo) 
      taskSummary = taskSummary.Where(x => x.Due <= dateCriterion.Value1); 
     else if (dateCriterion.Condition == DateCondition.GreaterThan) 
      taskSummary = taskSummary.Where(x => x.Due > dateCriterion.Value1); 
     else if (dateCriterion.Condition == DateCondition.GreaterThanOrEqualTo) 
      taskSummary = taskSummary.Where(x => x.Due >= dateCriterion.Value1); 
     else if (dateCriterion.Condition == DateCondition.EqualTo) 
      taskSummary = taskSummary.Where(x => x.Due == dateCriterion.Value1); 
     else if (dateCriterion.Condition == DateCondition.Between) 
      taskSummary = taskSummary.Where(x => x.Due <= dateCriterion.Value1 && x.Due >= dateCriterion.Value2); 

    return taskSummary; 
} 

Répondre

1

Vous devez prendre l'expression lambda comme un arbre d'expression comme ceci:

protected virtual IQueryable<TaskView> AddTaskDuePredicate(
    Expression<Func<TaskView, DateTime>> projection, 
    DateCriteria dateCriterion, 
    IQueryable<TaskView> taskSummary) 

Ensuite, vous auriez à construire une Expression<Func<TaskView, bool>> de cette projection, en utilisant des choses comme Expression.GreaterThan et Expression.Lambda. Du haut de ma tête:

ParameterExpression p = projection.Parameters[0]; 
Expression constant = Expression.Constant(dateCriterion.Value1); 
Expression comparison = Expression.GreaterThan(projection.Body, constant); 
Expression lambda = Expression.Lambda<Func<TaskView, bool>> 
    (comparison, p); 
taskSummary = taskSummary.Where(lambda); 

C'est complètement non testé cependant. Évidemment, une fois que vous avez ce travail pour GreaterThan, le reste devrait être relativement facile ...

+0

Merci, Jon qui est ce que je avais besoin. –

0

Voici ce que j'ai fini avec. Je peux appeler cette méthode comme paramètre .Lorsque() donc,

taskSummary.Where(AddDatePredicate<TaskView>(x => (DateTime)x.Due, filterInfo.Due)); 

     protected virtual Expression<Func<T, bool>> AddDatePredicate<T>(Expression<Func<T, DateTime>> projection, DateCriteria dateCriterion) 
     { 
      ParameterExpression p = projection.Parameters[ 0 ]; 
      Expression constant = Expression.Constant((DateTime)dateCriterion.Value1); 

      Expression comparison; 
      switch(dateCriterion.Condition) 
      { 
       case DateCondition.GreaterThan : 
        comparison = Expression.GreaterThan(projection.Body, constant); 
        break; 
       case DateCondition.GreaterThanOrEqualTo: 
        comparison = Expression.GreaterThanOrEqual(projection.Body, constant); 
        break; 
       case DateCondition.LessThan: 
        comparison = Expression.LessThan(projection.Body, constant); 
        break; 
       case DateCondition.LessThanOrEqualTo: 
        comparison = Expression.LessThanOrEqual(projection.Body, constant); 
        break; 

       case DateCondition.Between: 
        { 
         var comparisonLeft = Expression.GreaterThanOrEqual(projection.Body, Expression.Constant((DateTime)dateCriterion.Value1)); 
         var comparisonRight = Expression.LessThanOrEqual( projection.Body, Expression.Constant((DateTime)dateCriterion.Value2)); 

         comparison = Expression.AndAlso(comparisonLeft, comparisonRight); 
         break; 
        } 
       default: 
        return null;//TODO:Something bad happens here. 
      }