如何从表达式树动态构造一个谓词方法? [英] How do I dynamically construct a predicate method from an expression tree?

查看:180
本文介绍了如何从表达式树动态构造一个谓词方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里是场景:
Silverlight 4.0,DataGrid,PagedCollectionView itemssource。
目的是将一个过滤器应用于PCV。过滤器需要是 Predicate< object>(方法) - 其中Method对象实现了一些逻辑,并返回true / false作为包含。
我有什么需要可选地包括3个不同的标准在过滤器逻辑和显式代码很快变得丑陋。我们不想这么做吗?

因此,我发现有一种方法可以使用PredicateBuilder构建一个表达式树,并将其传递给Linq。其中,一个la :

  IQueryable< Product> SearchProducts(params string [] keywords)
{
var predicate = PredicateBuilder.False< Product>();

foreach(关键字中的字符串关键字)
{
string temp = keyword;
predicate = predicate.Or(p => p.Description.Contains(temp));
}
返回dataContext.Products.Where(谓词);

$ / code $ / pre

这不是我想要做的事情/ p>

使用3个可选标准,我想写下如下所示:

  Ratings.Filter = BuildFilterPredicate(); // Ratings = PagedCollectionView 


私有谓词< object> BuildFilterPredicate()
{
bool FilterOnOrder =!String.IsNullOrEmpty(sOrderNumberFilter);
var predicate = PredicateBuilder.False< object>();
if(ViewMineOnly)
{
predicate = predicate.And(Rating r => sUserNameFilter == r.Assigned_To); (ViewStarOnly)
{
predicate = predicate.And(Rating r => r.Star.HasValue&& r.Star.Value> 0;
}
); (FilterOnOrder)
{
predicate = predicate.And(Rating r => r.ShipmentInvoice.StartsWith(sOrderNumberFilter));

if
}
返回谓词;



$ b当然这不会编译,因为PredicateBuilder会创建一个表达式< Func< T,bool>> 不是一个实际的谓词方法。但是我发现有一些方法可以将表达式树转换为方法,所以在我看来应该有一种方法来完成我所做的事情,而不需要使用一堆嵌套的if / then / else语句。



所以问题是 - 是否有动态构建谓词方法的方法?

TIA

解决方案

要为PagedCollectionView执行此操作,您需要有一个谓词。所以它看起来像:

  private Predicate< object> ConvertExpressionToPredicate(Expression< Func< object,bool>> exp)
{
Func< object,bool> func = exp.Compile();
谓词< object> predicate = new Predicate< object>(func);
//谓词< object> predicate = t => FUNC(T); //也可以工作
//谓词< object>谓词= func.Invoke; //也可以工作
返回谓词;





构建表达式:

  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 ||(评分)r).Assigned_To.Trim()。ToUpper()==UNCLAIMED); (ViewStarOnly)
{
predicate = predicate.And(r =>((Rating)r).Star.HasValue&&((Rating) r).Star.Value> 0);如果(FilterOnOrder)
{
predicate = predicate.And(r =>((Rating)r).ShipmentInvoice.Trim()。ToUpper()。StartsWith (sOrderNumberFilter)); (ViewDueOnly)
{
predicate = predicate.And(r =>((Rating)r).SettlementDueDate< = ThisThursday);
}
}
返回谓词;
}

然后设置过滤器:

  Ratings.Filter = ConvertExpressionToPredicate(BuildFilterExpression()); 


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?

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]

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;
}

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

解决方案

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;
}

and build the expression:

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;
}

and then set the filter:

Ratings.Filter = ConvertExpressionToPredicate(BuildFilterExpression());

这篇关于如何从表达式树动态构造一个谓词方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆