2009-08-23 6 views
2

Je veux créer la requête suivante dans les arbres d'expression:obtenir l'expression de la méthode dans l'arbre d'expression

var test = from datarow in tempResults 
      where datarow.Field<String>("ColumnName") == "Column" 
      select datarow; 

Comment puis-je créer l'expression:

datarow.Field<String>("ColumnName")? 

i tout essayé, je même suis coincé lors de l'obtention du MethodInfo of Field pour la méthode Expression.Call. Le champ est une méthode d'extension de DataRowExtentions.

Est-ce que je dois utiliser Expression.Call() pour cela? Comment puis-je obtenir le MethodInfo? y a-t-il une manière plus simple de le faire?

i essayé:

ParameterExpression datarow = Expression.Parameter (typeof (DataRowExtensions), "datarow"); Expression à gauche = Expression.Call (dataRow, typeof (DataRowExtensions) .GetMethod ("Field"));

mais cela ne fonctionne pas. Je souhaite créer des filtres dynamiques sur les données dans IQueryable tempResults.

L'utilisateur va cocher les cases à cocher de l'interface graphique qui ajoutera des expressions "Where" aux données de tempResults. lorsque l'utilisateur choisit "Colonne" je veux présenter les DataRows où ColumnName = "Column". C'est pourquoi j'ai besoin de créer l'expression where. mais je suis tellement coincé sur la chose MethodInfo. J'ai essayé cela aussi:

MethodInfo FieldStringMethodInfo = typeof(DataRowExtensions).GetMethod("Field", BindingFlags.Public | BindingFlags.Static); 

mais cela ne fonctionne pas aussi.

Existe-t-il d'autres façons de le faire?

Répondre

2

réponse de remplacement précisions suivantes dans les commentaires:

Pour successivement la construction de filtres supplémentaires, vous n'avez pas besoin d'arbres d'expression; vous pouvez appeler .Where plusieurs fois (si nécessaire, une fois par terme de recherche) - par exemple:

IEnumerable<DataRow> query = tempResults.AsEnumerable(); 
if(!string.IsNullOrEmpty(value1)) { 
    query = query.Where(row => row.Field<string>("Col1") == value1); 
} 
if (!string.IsNullOrEmpty(value2)) { 
    query = query.Where(row => row.Field<string>("Col2") == value2); 
} 

La seule chose à regarder est la question « de capture »; Veillez à ne pas réutiliser l'un des value1, value2 etc - sinon la dernière valeur s'appliquera aux précédents filtres ...


Pour un exemple de combinaison des délégués (des commentaires) - note que je « ai laissé tomber l'aspect DataTable ici uniquement pour rendre l'exemple plus court (il fonctionnera de manière identique):

public static class Predicate { 
    public static Func<T, bool> OrElse<T>(
      this Func<T, bool> lhs, Func<T, bool> rhs) { 
     return lhs == null ? rhs : obj => lhs(obj) || rhs(obj); 
    } 
    public static Func<T, bool> AndAlso<T>(
      this Func<T, bool> lhs, Func<T, bool> rhs) { 
     return lhs == null ? rhs : obj => lhs(obj) && rhs(obj); 
    } 
} 
class Data { 
    public string Color { get; set; } 
} 
class Program { 
    static void Main() { 
     bool redChecked = true, greenChecked = true; // from UI... 
     List<Data> list = new List<Data>() { 
      new Data { Color = "red"}, 
      new Data { Color = "blue"}, 
      new Data { Color = "green"}, 
     }; 
     Func<Data, bool> filter = null; 
     if (redChecked) { 
      filter = filter.OrElse(row => row.Color == "red"); 
     } 
     if (greenChecked) { 
      filter = filter.OrElse(row => row.Color == "green"); 
     } 
     if (filter == null) filter = x => true; // wildcard 

     var qry = list.Where(filter); 

     foreach (var row in qry) { 
      Console.WriteLine(row.Color); 
     } 
    } 
} 

(réponse originale)

En fait, cette variante de LINQ n'utilisera pas d'arborescence d'expression ...il utilisera un délégué; mais vous pouvez construire l'arbre et le compiler si vous voulez vraiment ... Je ne sais pas pourquoi vous le feriez, cependant. Qu'est-ce que tu veux faire? Je vais frapper un exemple ...


Ici vous allez; cela utilise un arbre d'expression, mais je ne peux pas penser à une seule bonne raison de le faire, sinon pour prouver que vous le pouvez!

public static class MyExtensions 
{ 
    public static IQueryable<TRow> Where<TRow, TValue>(
     this IQueryable<TRow> rows, 
     string columnName, TValue value) 
     where TRow : DataRow 
    { 
     var param = Expression.Parameter(typeof(TRow), "row"); 
     var fieldMethod = (from method in typeof(DataRowExtensions).GetMethods() 
          where method.Name == "Field" 
          && method.IsGenericMethod 
          let args = method.GetParameters() 
          where args.Length == 2 
          && args[1].ParameterType == typeof(string) 
          select method) 
          .Single() 
          .MakeGenericMethod(typeof(TValue)); 
     var body = Expression.Equal(
      Expression.Call(null,fieldMethod, 
       param, 
       Expression.Constant(columnName, typeof(string))), 
      Expression.Constant(value, typeof(TValue)) 
     ); 
     var lambda = Expression.Lambda<Func<TRow, bool>>(body, param); 
     return rows.Where(lambda); 

    } 
} 
class Program 
{ 
    static void Main(string[] args) 
    { 
     DataTable tempResults = new DataTable(); 
     tempResults.Columns.Add("ColumnName"); 
     tempResults.Rows.Add("foo"); 
     tempResults.Rows.Add("Column"); 

     var test = tempResults.AsEnumerable().AsQueryable() 
        .Where("ColumnName", "Column"); 
     Console.WriteLine(test.Count()); 

    } 
} 
+0

Je veux créer des filtres dynamiques sur les données contenues dans IQueryable tempResults. L'utilisateur va cocher les cases à cocher de l'interface graphique qui ajoutera des expressions "Where" aux données de tempResults. Lorsque l'utilisateur choisit "Colonne", je souhaite présenter les DataRows où ColumnName = "Column". c'est pourquoi j'ai besoin de créer l'expression where. mais je suis tellement coincé sur la chose MethodInfo .... J'ai essayé aussi: MethodInfo FieldStringMethodInfo = type de (DataRowExtensions) .GetMethod ("Champ ", BindingFlags.Public | BindingFlags.Static); cela ne fonctionne pas aussi. Existe-t-il d'autres façons de le faire? – Rodniko

+0

Ahh! Vous n'avez pas besoin d'arbres d'expression pour cela ... voir mise à jour (dessus de) –

+0

Merci marc, l'exemple Asenumerable() est bon mais j'ai besoin d'un moyen de le créer dynamiquement, car l'utilisateur peut choisir: row = > row.Field ("Col1") == valeur1 || row.Field ("Col1") == valeur2 et la prochaine fois: row => row.Field ("Col1") == value1 || row.Field ("Col1") == valeur2 || row.Field ("Col1") == value3 C'est pourquoi j'ai besoin de le composer dynamiquement, je dois trouver un moyen de "Ajouter les filtres que je veux à une clause where" et ensuite seulement exécuter la requête. puis-je faire cela d'une manière plus simple que l'exemple de l'arbre d'expression? – Rodniko

Questions connexes