У меня острый вопрос о преобразовании выражений Linq.У меня был хороший поиск, но я не смог найти ничего, что могло бы охватить этот случай.Я достаточно знаком с Linq, по крайней мере, с точки зрения создания и передачи лямбда-методов в методы, но я немного слабее в вещах Expression.
Во-первых, некоторый контекст: у меня есть универсальное решение по сохранению, основанное на NHibernate, которое используется в ряде проектов DDD.Для особых случаев, когда заданная коллекция дочерних элементов в совокупности может быть по существу бесконечной (т. Е. Очень большой), я не могу просто отобразить набор или сумку, поскольку никогда не будет приемлемо, чтобы вся коллекция была загружена в память.В этой архитектуре код, использующий API, не может напрямую взаимодействовать с репозиторием для выполнения запроса или ограничения результатов таким образом.Конечно, я мог бы вообще не иметь коллекцию в API и предоставлять методы для извлечения соответствующих подмножеств дочерних объектов (а если это не сработает, это то, что я буду делать), но я пытаюсь сделать что-то немного другоеи у меня почти все получилось ...
Эти проекты отображаются с помощью Fluent (не с автоматическим отображением), поэтому я добавил метод в класс базовой карты вform
HasManyQueryable<TCollection>(Expression<Func<T, IQueryable<TCollection>>> memberExpression, Expression<Func<T, TCollection, bool>> selector)
Этот метод извлекает релевантный PropertyInfo
из первого Expression
(который указывает член для сопоставления).Селектор Expression
содержит отношение между родительским и дочерним объектами в качестве замены обычного отображения NHibernate.
Итак, предположим, у меня есть селектор на карте для типа домена User
(который является T
выше):
HasManyQueryable<Transaction>(x => x.Transactions, (u, t) => t.User == u);
Указывает отображение между подмножеством всех Transactions
, где Transaction.User
- это предоставленное User
u , и свойством User.Transactions
что IQueryable<Transaction>
.Когда создается реальный объект User
, мне нужно превратить его в
Expression<Func<Transaction, bool>> expression = (t => t.User == this)
, где this
- это строящийся объект User
.Другими словами, я хочу взять общее правило, которое говорит, как сопоставить Users
с Transactions
и превратить его в правило о сопоставлении this User
с Transactions
.Затем я могу использовать это выражение для генерации IQueryable<Transaction>
из репозитория, выполнив запрос Linq, таким образом:
return Repository.For<Transaction>().Where(selector);
Это может работать только тогда, когда селектор равен Func<Transaction, bool>
, поэтому моя конечная необходимость состоит в том, чтобыпревратить исходное выражение, которое сгенерирует Func<User, Transaction, bool>
в Func<Transaction, bool>
.
. Это дает мне коллекцию IQueryable
, где все операции запроса выполняются как запросы Linq-to-NHibernate и, таким образом, веськоллекция никогда не загружается в память (да, я знаю, что вы могли бы создать запрос, который фактически заставил бы его это сделать, но я могу перехватить его во время проверки кода).
Фу.Надеюсь, что это имеет смысл.
Кто-нибудь с навыками переписывания leet Expression способен указать мне правильное направление?