tags:

views:

30

answers:

2

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 )
            taskSummary = taskSummary.Where( x => x.Due <= dateCriterion.Value1 && x.Due >= dateCriterion.Value2 );

    return taskSummary;
}
+2  A: 

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...

Jon Skeet
Thanks, Jon that's what i needed.
Aaron Fischer
+1  A: 

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.
            }
Aaron Fischer