Лучшее, что вы можете сделать, это зафиксировать предикат в Expression<>
. Метод уже скомпилирован в IL и поэтому не может быть выделен провайдером Linq.
Expression<Func<DamageList, bool>> predicate = item => item.DamageCount > 5;
Затем вы можете передать этот предикат непосредственно в Where
:
var q = session.Linq<DamageList>().Where(predicate);
Если вы хотите динамически объединить два таких выражения, вы либо записываете код для обоих в одно выражение, либо записываете оба в отдельные выражения. Это усложняется, потому что вам нужно, чтобы каждый из них ссылался на передаваемый item
. Это действительно другой вопрос, который уже задан: Как динамически создать предикат Expression‹Func‹MyClass, bool››?
Вы можете написать составной предикат, используя оператор &&, и при этом зафиксировать его в выражении:
Expression<Func<DamageList, bool>> predicate =
dl => dl.DamageCount > 5 && dl.Name.Contains(criteria);
Вы спрашиваете о вызове методов в таком выражении — ну, этот пример действительно вызывает метод!
Он строит дерево из Expression
узлов различных типов. Где-то будет включен узел вызова метода, в котором говорится о вызове метода Contains
для string
(при условии, что Name
является string
). Итак, это пример инструкции вызова метода, встроенной в выражение. Чтобы это работало, поставщик Linq должен знать, что делает этот метод, чтобы он мог преобразовать его в эквивалентный SQL (как в случае с типичной системой ORM).
Таким образом, вы можете встраивать определенные стандартные вызовы методов в выражения — для этого требуется, чтобы провайдер Linq знал о них. Методы string
хорошо определены, но не каждый провайдер обязательно сможет работать со всеми из них.
Для провайдера Linq не было бы невозможно разрешить вам добавлять свои собственные расширения, которые обрабатывают дополнительные методы, но я не знаю ни одного, поддерживающего это (очевидно, если система с открытым исходным кодом, вы можете добавить свои собственные).
Подводя итог, поставщику Linq требуется дерево узлов выражений, которое он может анализировать для преобразования в какой-либо другой язык, например SQL, для выполнения в другом контексте, например, внутри удаленной базы данных. Если вы пишете обычные методы, компилятор C# скомпилирует их в низкоуровневый исполняемый IL, а не в узлы выражений. Так что это похоже на тупик: нет встроенного средства для превращения IL обратно в узлы выражения.
person
Daniel Earwicker
schedule
21.02.2010