扩展IQueryable并解析属性

时间:2009-07-27 08:03:51

标签: c# c#-3.0

我对linq很新,并希望通过扩展IQueryable来深入研究。我想创建一个查询日期范围的简单扩展方法。某些东西相当于:

IQuerable.Where(x => x.Date > fromDate && x.Date < toDate);

但是在日期上有一些额外的处理。我希望能够解析一个属性来执行查询,因此方法调用将类似于:

IQueryable.WhereDateRange(x => x.Date, fromDate, toDate);
IQueryable.WhereDateRange(x => x.AnotherDate, fromDate, toDate);

我一直在寻找类似下面的东西,但我不完全确定我在做什么

public static IQueryable<T> WhereDateRange<T>(this IQueryable<T> source, Func<T, DateTime> getter, DateTime from, DateTime to) {
//query here
}

这可能吗?如果可以,我该怎么做?

1 个答案:

答案 0 :(得分:4)

未经测试,但是:

public static IQueryable<T> WhereDateRange<T>(
    this IQueryable<T> source, Expression<Func<T, DateTime>> getter,
    DateTime from, DateTime to)
{
    Expression body = getter.Body;

    var predicate = Expression.Lambda<Func<T, bool>>(
        Expression.And(
            Expression.GreaterThan(body, Expression.Constant(from)),
            Expression.LessThan(body, Expression.Constant(to))
        ),
        getter.Parameters);
    return source.Where(predicate);
}

但是,有关信息;我通常假设范围是>= start< end,所以我会使用Expression.GreaterThanOrEqual

让它更可重用(并注意到我在这里使用GreaterThanOrEqual):

public static IQueryable<T> WhereInRange<T, TValue>(
    this IQueryable<T> source, Expression<Func<T, TValue>> selector,
    TValue from, TValue to)
{
    Expression body = selector.Body;

    var predicate = Expression.Lambda<Func<T, bool>>(
        Expression.And(
            Expression.GreaterThanOrEqual(
                body, Expression.Constant(from, typeof(TValue))),
            Expression.LessThan(
                body, Expression.Constant(to, typeof(TValue)))
        ),
        selector.Parameters);
    return source.Where(predicate);
}

(在这种情况下需要在常量上指定TValue,因为null否则会导致大问题)