По этому вопросу я буду использовать стандартную структуру продуктов (с флагом IsActive) и OrderItems (каждая ссылка на Продукт). У меня также есть построитель запросов, который генерирует выражения Linq, используемые для запроса продуктов. Образец фильтр позволит пользователю найти активные/неактивные продукты, создавая выражение Linq, как:Преобразование Linq MemberExpression lambda для работы со классом со ссылкой
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 к Entities) не поддерживает Expression.Invoke
.
Есть ли способ взять MemberExpression от testProductActive
и превратить его в !orderItem.Product.IsActive
?
Примечания: В реальной жизни, например, я бы коллекция Expression<Func<Product, bool>>
выражений, генерируемых видимые фильтры, которые будут преобразованы все потребности. Прямо сейчас у меня есть фильтры, генерирующие выражения для обоих типов записей, но я хотел бы отказаться от дублирования и сделать так, чтобы существующий фильтр можно было использовать для записи другого типа без изменения собственного кода фильтра.
Был старый вопрос, который показал посетителю для объединения Expresson.Invoke - ищет его ... –
Найдено это: http://stackoverflow.com/questions/1717444 - это позволит вам использовать 'Expression.Invoke', но сгладить его до одного (' Invoke'-free) 'Expression'. Не уверен, что это тогда обман? –
@Mark, активируйте свой ответ, потому что он выглядит круто! –