For this question, I'll use the standard structure of Products (with an IsActive flag) and OrderItems (that each reference a Product). I also have a query builder that generates Linq expressions used to query products. A sample filter would let the user find active/inactive products, generating a Linq expression like:
Expression<Func<Product, bool>> testProductActive = product => !product.IsActive;
I want to take that expression and use it to test an IQueryable<OrderItem>
. I can do it with in-memory collections using 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;
}
Which I would call like:
Expression<Func<OrderItem, bool>> testOrderItemProductActive = testProductActive.Translate<Product, OrderItem, bool>(orderItem => orderItem.Product);
But NHibernate.Linq (and from what I've seen in questions, Linq to Entities) does not support Expression.Invoke
.
Is there a way to take the MemberExpression from testProductActive
and turn it into !orderItem.Product.IsActive
?
Note: In a real-life example, I would have a collection of Expression<Func<Product, bool>>
expressions generated by visible filters that would all need converted. Right now I've got my filters generating expressions for both types of records, but I'd love to drop the duplication and make it so an existing filter could be used for a different type of record without changing the filter's own code.