I have a method to add a date condition to my linq query. What I want to do is pass x.Due in as a parameter to make this able to work with any date. Any Ideas?
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 )
task开发者_StackOverflow中文版Summary = taskSummary.Where( x => x.Due <= dateCriterion.Value1 && x.Due >= dateCriterion.Value2 );
return taskSummary;
}
You would have to take the lambda expression as an expression tree like this:
protected virtual IQueryable<TaskView> AddTaskDuePredicate(
Expression<Func<TaskView, DateTime>> projection,
DateCriteria dateCriterion,
IQueryable<TaskView> taskSummary)
Then you'd have to build an Expression<Func<TaskView, bool>>
from that projection, using things like Expression.GreaterThan
and Expression.Lambda
. Off the top of my head:
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);
That's completely untested though. Obviously once you've got this working for GreaterThan
, the rest should be relatively easy...
Here is what I ended up with. I can call this method as a .Where() parameter so,
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.
}
精彩评论