2016-04-06 3 views
1

Wie der Titel sagt, versuche ich, einen Ausdrucksbaum zum Prüfen zu erzeugen, wenn ein Element in einer Liste von Zeichenfolgen entsprechen einer Zeichenfolge eines Buchobjekts.Generieren eines Ausdrucksbaums für List.Any (v => v.Contains (Book.Title.ToString()))

Bisher habe ich diese bekam:

private static Expression<Func<Books, bool>> GenerateListContainsLikeExpression(string propertyName, List<string> values) 
    { 
     var parameter = Expression.Parameter(typeof(Books), "b"); 
     var listParameter = Expression.Parameter(typeof(string), "v"); 
     var property = Expression.Property(parameter, propertyName); 
     var anyMethod = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public).First(m => m.Name == "Any" && m.GetParameters().Count() == 2).MakeGenericMethod(typeof(string)); 
     var toStringMethod = typeof(object).GetMethod("ToString"); 
     var containsMethod = typeof(string).GetMethod("Contains"); 
     var objectString = Expression.Call(property, toStringMethod); 
     var lambda = Expression.Call(listParameter, containsMethod, objectString); 
     var func = Expression.Lambda<Func<List<string>, bool>>(lambda, parameter); 
     var comparison = Expression.Call(anyMethod, Expression.Constant(values), func); 

     return Expression.Lambda<Func<Books, bool>>(comparison, parameter); 
    } 

Aber ich bin immer diese Fehlermeldung:

Expression of type 'System.Boolean' cannot be used for parameter of type 'System.Func 2[System.String,System.Boolean]' of method 'Boolean Any[String](System.Collections.Generic.IEnumerable 1[System.String], System.Func`2[System.String,System.Boolean])'

An dieser Linie:

var comparison = Expression.Call(anyMethod, Expression.Constant(values), lambda); 

ich, wie ich fühle mich einfach brauche das letzte bisschen.

Vielen Dank im Voraus :-)

EDIT: Zur Klarstellung. Ich werde ein wenig detaillierter erklären, was ich brauchte.

Ich musste Bücher basierend auf einigen der Bücher Eigenschaften kategorisieren. In diesem speziellen Fall übergebe ich eine Liste von Strings an die Funktion. Ich musste überprüfen, ob eine dieser Zeichenfolgen in irgendeinem Büchertitel enthalten war.

Also zuerst, das Lambda, von dem ich dachte, dass ich es brauchte, war falsch, um damit zu beginnen. Dies ist das Lambda, die ich tatsächlich benötigt: b => values.Any(v => b.Title.ToString().Contains(v))

Und hier ist der letzte Code, den ich am Ende mit:

private static Expression<Func<Books, bool>> GenerateListContainsLikeExpression(string propertyName, List<string> values) 
    { 
     var parameter = Expression.Parameter(typeof(Books), "b"); 
     var listParameter = Expression.Parameter(typeof(string), "v"); 
     var property = Expression.Property(parameter, propertyName); 
     var anyMethod = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public).First(m => m.Name == "Any" && m.GetParameters().Count() == 2).MakeGenericMethod(typeof(string)); 
     var toStringMethod = typeof(object).GetMethod("ToString"); 
     var containsMethod = typeof(string).GetMethod("Contains"); 
     var objectString = Expression.Call(property, toStringMethod); 
     var lambda = Expression.Call(objectString, containsMethod, listParameter); 
     var func = Expression.Lambda<Func<string, bool>>(lambda, listParameter); 
     var comparison = Expression.Call(anyMethod, Expression.Constant(values), func); 

     return Expression.Lambda<Func<Books, bool>>(comparison, parameter); 
    } 
+0

Ihre Funktion ist wahrscheinlich nicht, was Sie denken, dass es ist, und wahrscheinlich vermasselt. Any ist eine Erweiterungsmethode. Sie müssten also die statische Methode in Ihrem Ausdruck aufrufen. Soll List eine Liste von Büchern sein? Sieht aus wie es ist, aber es scheint, dass Sie das Argument für das Any Func behandeln, um eine Liste selbst zu sein, nicht eines der Bücher in der Liste. Alles sieht falsch aus ... Ich denke, es gibt einen Lambda => Ausdruckkonverter, den Sie verwenden können, um zu lernen, wie das Zeug funktioniert ... lemme peek for it. – Will

+0

Ja, ich denke, Sie können einfach gehen Expression > expr = x => x.Any (v => v.Contains (Book.Title.ToString()))) 'und dann den Ausdruck innerhalb der schnellen untersuchen schaue dir das Fenster an, um zu sehen, wie es aufgebaut ist. Auch hier weiß ich nicht, was dein 'TInput' aus dem Lambda in deinem Titel ist. – Will

+0

Ich habe den Post bearbeitet, damit Sie die vollständige Methode sehen können. –

Antwort

1

Abschlussarbeitscode:

private static Expression<Func<Books, bool>> GenerateListContainsLikeExpression(string propertyName, List<string> values) 
{ 
    var parameter = Expression.Parameter(typeof(Books), "b"); 
    var listParameter = Expression.Parameter(typeof(string), "v"); 
    var property = Expression.Property(parameter, propertyName); 
    var anyMethod = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public).First(m => m.Name == "Any" && m.GetParameters().Count() == 2).MakeGenericMethod(typeof(string)); 
    var toStringMethod = typeof(object).GetMethod("ToString"); 
    var containsMethod = typeof(string).GetMethod("Contains"); 
    var objectString = Expression.Call(property, toStringMethod); 
    var lambda = Expression.Call(objectString, containsMethod, listParameter); 
    var func = Expression.Lambda<Func<string, bool>>(lambda, listParameter); 
    var comparison = Expression.Call(anyMethod, Expression.Constant(values), func); 

    return Expression.Lambda<Func<Books, bool>>(comparison, parameter); 
} 

Für eine genaue Erklärung der das Problem. Siehe meine Bearbeitung im ursprünglichen Beitrag.

Verwandte Themen