Определите, где применяется IQueryable <T> - PullRequest
6 голосов
/ 26 октября 2011

Как я могу определить, применен ли IQueryable<T> фильтр where?

В этом коде мне нужно программно знать, что queryFiltered имеет к нему where, а query не

IQueryable<Customer> query = Context.Customers;
IQueryable<Customer> queryFiltered = Context.Customers
                                            .Where(c=>c.Name.Contains("ABC"));

Ответы [ 3 ]

9 голосов
/ 26 октября 2011

Вам нужно будет проанализировать Expression, который возвращается из свойства Expression в реализации IQueryable<T>.

Вам придется запросить метод Queryable.Where , вызываемый при сканировании дерева Expression.

Также обратите внимание, что пока Queryable.Where будет наиболеераспространенный способ обнаружения фильтра where, синтаксис запроса позволяет использовать другие реализации (в зависимости от того, какие пространства имен используются в директивах using );если у вас есть что-то, что не использует метод расширения Queryable.Where, тогда вам придется искать это явно (или использовать более общий метод фильтрации для метода Where, который принимает IQueryable<T> и возвращает IQueryable<T>).

Класс ExpressionVisitor (как указывает xanatos ) обеспечивает очень простой способ обхода дерева Expression, я настоятельно рекомендую использоватьэтот подход является основой для обработки вашего Expression дерева.

Следует отметить, что реализации класса ExpressionVisitor необходимы для хранения и представления состояния на уровне класса.Из-за этого было бы лучше (IMO) создать внутренние классы, которые выполняют действие один раз, а затем иметь открытый метод, который каждый раз создает новый экземпляр ExpressionVisitor;это поможет справиться с изменяющимся состоянием и, если все сделано правильно, позволит методу быть также потокобезопасным (если это ваше дело).

3 голосов
/ 26 октября 2011

Если вы используете C # 4.0, вы можете использовать этот пример кода: Получить все вызовы "где", используя ExpressionVisitor

Он основан на ExpressionVisitor.Он «посещает» различные элементы IQueryable<T>, чтобы найти Where детали.Это кажется достаточно простым.

Если вы используете C # = 3.5, вы можете использовать ExpressionVisitor образец из MSDN Как: реализовать посетитель дерева выражений PLUS WhereFinder изпредыдущая ссылка (они работают вместе, только что протестировано)

Чтобы использовать код:

var wf = new WhereFinder();
var wheres = wf.GetWhere(query.Expression);

if (wheres.Any())
{
    // There are Where in the query!
}

Если вы (правильно) так же параноидальны, как Rune FS, к WereFinder.VisitMethodCallизмените if на

if (expression.Method.Name == "Where" && expression.Method.DeclaringType.FullName == "System.Linq.Queryable")
1 голос
/ 26 октября 2011

Самый простой способ - позвонить q.Expression.ToString().Contains(".Where("). Как видите, query.Expression.ToString().Contains(".Where(") возвращает false, а queryFiltered.Expression.ToString().Contains(".Where(") возвращает true.

Вам может понадобиться больше сложности, чем если вы считаете другие выражения «фильтрацией», но это также верно и для подхода с использованием выражений для посетителей.

В этом есть что-то довольно хакерское, я дам вам, но это кажется намного проще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...