Wie konstruiere ich dynamisch eine Prädikatmethode aus einem Ausdrucksbaum?

expression-trees filter predicatebuilder silverlight

Frage

Hier ist das Szenario: Silverlight 4.0, DataGrid, PagedCollectionView itemssource. Ziel ist es, einen Filter auf den PCV anzuwenden. Der Filter muss ein Predicate<object>(Method) - wobei Methode eine Logik gegen das Objekt implementiert und Wahr / Falsch für die Aufnahme zurückgibt. Was ich habe, ist die Notwendigkeit, optional 3 verschiedene Kriterien in die Filterlogik aufzunehmen, und expliziter Code wird schnell hässlich. Das wollen wir nicht, oder?

So sehe ich, dass es eine Möglichkeit gibt, einen Ausdrucksbaum mit PredicateBuilder zu erstellen und diesen in Linq zu übergeben. Wo, 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);
}

[das ist nicht, was ich versuche, übrigens]

Mit 3 optionalen Kriterien möchte ich etwas schreiben wie:

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

Natürlich wird dies nicht kompiliert, da PredicateBuilder einen Expression<Func<T, bool>> keine tatsächliche Prädikatmethode. Aber ich sehe, dass es Möglichkeiten gibt, einen Ausdrucksbaum in eine Methode umzuwandeln, so dass es mir schien, dass es einen Weg geben sollte, um das zu erreichen, wonach ich suchte, ohne auf eine Menge verschachtelter if / then / else-Anweisungen zurückzugreifen.

Die Frage ist also - gibt es eine Möglichkeit, eine Prädikatenmethode dynamisch zu erstellen?

TIA

Beliebte Antwort

Um dies für eine PagedCollectionView zu tun, müssen Sie ein Prädikat haben. So sieht es aus:

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

und baue den Ausdruck:

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

und dann den Filter setzen:

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



Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum