如何删除或覆盖现有IQueryable中的where子句

时间:2017-07-25 16:22:02

标签: c# iqueryable

假设以下预过滤的IQueryable:

var query = items.Where(i => i.PropertyName == "Some property");
来自第三方库的

是否可以完全删除Where子句,或者将其替换为:

.Where(i => i.PropertyName == null || i.PropertyName == "Some property")

我已经看到提到能够在运行中重写IQueryable。这种方法会有任何缺点吗?我该怎么做呢?还有更好的方法吗?

更新

我已经设法用Ivan建议的ExpressionVisitor一起拼凑一些东西:

public class WhereRemoveVisitor : ExpressionVisitor
{
    protected override Expression VisitMethodCall(MethodCallExpression node)
    {
        if (node.Method.Name == "Where" && node.Method.DeclaringType == typeof(Queryable))
            return node.Arguments[0];
        else
            return base.VisitMethodCall(node);
    }
}

public static class IQueryableExtensions
{
    public static IQueryable<T> RemoveWhere<T>(this IQueryable<T> expression)
    {
        return Expression.Lambda<IQueryable<T>>(new WhereRemoveVisitor().Visit(expression.Expression)).Compile();
    }
}

虽然编译得很好,但它会在扩展方法中抛出“Lambda类型参数必须从System.Delegate派生”。

1 个答案:

答案 0 :(得分:2)

根据Ivan的建议,我设法使用ExpressionVisitor放置了一些东西:

public class WhereRemoveVisitor : ExpressionVisitor
{
    protected override Expression VisitMethodCall(MethodCallExpression node)
    {
        if (node.Method.Name == "Where" && node.Method.DeclaringType == typeof(Queryable))
            return node.Arguments[0];
        else
            return base.VisitMethodCall(node);
    }
}

public static class IQueryableExtensions
{
    public static IQueryable<T> RemoveWhere<T>(this IQueryable<T> expression)
    {
        var delExpr = Expression.Lambda<Func<IQueryable<T>>>(new WhereRemoveVisitor().Visit(expression.Expression)).Compile();
        return delExpr();
    }
}