Для этого вопроса я буду использовать стандартную структуру Products (с флагом IsActive) и OrderItems (каждая из которых ссылается на Product). У меня также есть конструктор запросов, который генерирует выражения Linq, используемые для запроса продуктов. Пример фильтра позволил бы пользователю находить активные / неактивные продукты, генерируя выражение Linq, например:
Expression<Func<Product, bool>> testProductActive = product => !product.IsActive;
Я хочу взять это выражение и использовать его для проверки IQueryable<OrderItem>
. Я могу сделать это с коллекциями в памяти, используя Expression.Invoke
:
public static Expression<Func<TDestination, TResult>> Translate<TSource, TDestination, TResult>(this Expression<Func<TSource, TResult>> @this, Expression<Func<TDestination, TSource>> getSourceFromDestination)
{
ParameterExpression param = Expression.Parameter(typeof(TDestination), "arg");
Expression invokedGetSource = Expression.Invoke(getSourceFromDestination, param);
Expression invokedOriginalBody = Expression.Invoke(@this, invokedGetSource);
Expression<Func<TDestination, TResult>> result = Expression.Lambda<Func<TDestination, TResult>>(invokedOriginalBody, param);
return result;
}
Который я бы назвал как:
Expression<Func<OrderItem, bool>> testOrderItemProductActive = testProductActive.Translate<Product, OrderItem, bool>(orderItem => orderItem.Product);
Но NHibernate.Linq (и из того, что я видел в вопросах, Linq to Entities) не поддерживает Expression.Invoke
.
Есть ли способ взять выражение члена из testProductActive
и превратить его в !orderItem.Product.IsActive
?
Примечание. В реальном примере у меня была бы коллекция Expression<Func<Product, bool>>
выражений, сгенерированных видимыми фильтрами, которые нужно преобразовать. Прямо сейчас у меня есть мои фильтры, генерирующие выражения для обоих типов записей, но я бы хотел убрать дублирование и сделать так, чтобы существующий фильтр мог использоваться для другого типа записи без изменения собственного кода фильтра.