如何从表达式树动态构造谓词方法? [英] How do I dynamically construct a predicate method from an expression tree?
问题描述
场景如下:Silverlight 4.0、DataGrid、PagedCollectionView 项目源.目标是将过滤器应用于 PCV.过滤器需要是一个 Predicate
- 其中 Method 对对象实现一些逻辑并返回真/假以供包含.我需要在过滤器逻辑中选择性地包含 3 个不同的标准,而显式代码很快就会变得丑陋.我们不想那样,对吗?
Here's the scenario:
Silverlight 4.0, DataGrid, PagedCollectionView itemssource.
The objective is to apply a Filter to the PCV. The filter needs to be a Predicate<object>(Method)
- where Method implements some logic against the object and returns true/false for inclusion.
What I have is a need to optionally include 3 different criteria in the filter logic and explicit code quickly gets ugly. We don't want that, do we?
所以我看到有一种方法可以使用 PredicateBuilder 构建表达式树并将其传递给 Linq.Where,a la:
So I see that there is a way to build an expression tree using PredicateBuilder and pass that into Linq.Where, a la:
IQueryable<Product> SearchProducts (params string[] keywords)
{
var predicate = PredicateBuilder.False<Product>();
foreach (string keyword in keywords)
{
string temp = keyword;
predicate = predicate.Or (p => p.Description.Contains (temp));
}
return dataContext.Products.Where (predicate);
}
[顺便说一句,这不是我想要做的]
[this is not what I'm trying to do by the way]
有 3 个可选条件,我想写一些类似的东西:
With 3 optional criteria, I want to write something like:
Ratings.Filter = BuildFilterPredicate(); // Ratings = the PagedCollectionView
private Predicate<object> BuildFilterPredicate()
{
bool FilterOnOrder = !String.IsNullOrEmpty(sOrderNumberFilter);
var predicate = PredicateBuilder.False<object>();
if (ViewMineOnly)
{
predicate = predicate.And(Rating r => sUserNameFilter == r.Assigned_To);
}
if (ViewStarOnly)
{
predicate = predicate.And(Rating r => r.Star.HasValue && r.Star.Value > 0);
}
if (FilterOnOrder)
{
predicate = predicate.And(Rating r => r.ShipmentInvoice.StartsWith(sOrderNumberFilter));
}
return predicate;
}
当然这不会编译,因为 PredicateBuilder 创建了一个 Expression
而不是实际的谓词方法.但是我看到有一些方法可以将表达式树转换为方法,因此在我看来,应该有一种方法来完成我所追求的目标,而无需求助于一堆嵌套的 if/then/else 语句.
Of course this won't compile because PredicateBuilder creates an Expression<Func<T, bool>>
not an actual predicate method. But I see that there are ways to convert an expression tree into a method so it seemed to me there ought to be a way to accomplish what I'm after without resorting to a bunch of nested if/then/else statements.
所以问题是 - 有没有办法动态构建谓词方法?
So the question is - is there a way to build a predicate method dynamically?
TIA
推荐答案
要为 PagedCollectionView 执行此操作,您需要有一个 Predicate.所以它看起来像:
to do this for a PagedCollectionView, you need to have a Predicate. So it looks like:
private Predicate<object> ConvertExpressionToPredicate(Expression<Func<object, bool>> exp)
{
Func<object, bool> func = exp.Compile();
Predicate<object> predicate = new Predicate<object>(func);
//Predicate<object> predicate = t => func(t); // also works
//Predicate<object> predicate = func.Invoke; // also works
return predicate;
}
并构建表达式:
private Expression<Func<object, bool>> BuildFilterExpression()
{
...snip...
var predicate = PredicateBuilder.True<object>();
if (ViewMineOnly)
{
predicate = predicate.And(r => ((Rating)r).Assigned_To.Trim().ToUpper() == sUserNameFilter || ((Rating)r).Assigned_To.Trim().ToUpper() == "UNCLAIMED");
}
if (ViewStarOnly)
{
predicate = predicate.And(r => ((Rating)r).Star.HasValue && ((Rating)r).Star.Value > 0);
}
if (FilterOnOrder)
{
predicate = predicate.And(r => ((Rating)r).ShipmentInvoice.Trim().ToUpper().StartsWith(sOrderNumberFilter));
}
if (ViewDueOnly)
{
predicate = predicate.And(r => ((Rating)r).SettlementDueDate <= ThisThursday);
}
return predicate;
}
然后设置过滤器:
Ratings.Filter = ConvertExpressionToPredicate(BuildFilterExpression());
这篇关于如何从表达式树动态构造谓词方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!