Используя LINQKit , вы можете написать свой метод (я предпочитаю в качестве метода расширения) примерно так:
public static class StudentExt {
public static IQueryable<Student> FilterAfterDate(this IQueryable<Student> query,
Expression<Func<Student, DateTime>> GetDateExpression, DateTime now)
=> query.AsExpandable().Where(x => GetDateExpression.Invoke(x) > now);
}
И используйте это так:
var q1 = query.FilterAfterDate(q => q.BirthDate, now);
var q2 = query.FilterAfterDate(q => q.EnrollmentDate, now);
var q3 = query.FilterAfterDate(q => q.GraduationDate, now);
Чтобы бросить свой собственный, вы просто используете обычный ExpressionVisitor
, который заменяет:
public static class ExpressionExt {
/// <summary>
/// Replaces an Expression (reference Equals) with another Expression
/// </summary>
/// <param name="orig">The original Expression.</param>
/// <param name="from">The from Expression.</param>
/// <param name="to">The to Expression.</param>
/// <returns>Expression with all occurrences of from replaced with to</returns>
public static Expression Replace(this Expression orig, Expression from, Expression to) => new ReplaceVisitor(from, to).Visit(orig);
}
/// <summary>
/// ExpressionVisitor to replace an Expression (that is Equals) with another Expression.
/// </summary>
public class ReplaceVisitor : ExpressionVisitor {
readonly Expression from;
readonly Expression to;
public ReplaceVisitor(Expression from, Expression to) {
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node) => node == from ? to : base.Visit(node);
}
Теперь, когда доступно Replace
, вы можете создать лямбда-шаблон и использовать его для замены в параметре Expression
:
public static class StudentExt {
public static IQueryable<Student> FilterAfterDate(this IQueryable<Student> query,
Expression<Func<Student, DateTime>> GetDateExpression, DateTime now) {
Expression<Func<DateTime,bool>> templateFn = x => x > now;
var filterFn = Expression.Lambda<Func<Student,bool>>(templateFn.Body.Replace(templateFn.Parameters[0], GetDateExpression.Body), GetDateExpression.Parameters);
return query.Where(filterFn);
}
}
И вы используете его так же, как с LINQKit.