对于这个问题,我将使用 Products(带有 IsActive 标志)和 OrderItems(每个都引用一个 Product)的标准结构。我还有一个查询生成器,可以生成用于查询产品的 Linq 表达式。示例过滤器可以让用户查找活动/非活动产品,生成一个 Linq 表达式,例如:
Expression<Func<Product, bool>> testProductActive = product => !product.IsActive;
我想采用该表达式并使用它来测试 IQueryable
。我可以使用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)不支持<代码>表达式.调用。
有没有办法从 testProductActive
获取 MemberExpression 并将其转换为 !orderItem.Product.IsActive
?
注意:在现实生活中的示例中,我将拥有由可见过滤器生成的 Expression>
表达式的集合,这些表达式都需要转换。现在,我已经让过滤器为两种类型的记录生成表达式,但我希望删除重复项并使其能够将现有过滤器用于不同类型的记录,而无需更改过滤器自己的代码。
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.
发布评论
评论(1)
它与您的提议不太一样,但请查看 动态 Linq。
It's not in quite the same vein as what you're proposing, but check out Dynamic Linq.