2010-08-16 1 views
5

Ich versuche im Grunde zu tun this, aber ich weiß nicht, was T sein wird, so dass ich Dinge mit Reflection und Expression Bäume aufbauen.Convert func zu Prädikat mit Reflektion in C#

// Input (I don't know about "Book") 
Type itemType = typeof(Book); 

// Actual Code 
// Build up func p => p.AuthorName == "Jon Skeet" 
ParameterExpression predParam = Expression.Parameter(itemType, "p"); 
Expression left = Expression.Field(predParam, itemType.GetField("AuthorName")); 
Expression right = Expression.Constant("Jon Skeet", typeof(string)); 
Expression equality = Expression.Equal(left, right); 
Delegate myDelegate = Expression.Lambda(equality, new ParameterExpression[] { predParam }).Compile(); // Not sure if I need this 

// Build up predicate type (Predicate<Book>) 
Type genericPredicateType = typeof(Predicate<>); 
Type constructedPredicateType = genericPredicateType.MakeGenericType(new Type[] { itemType }); 

// I need an instance to use this predicate, right? (** This Fails **) 
object predicateInstance = Activator.CreateInstance(constructedPredicateType, new object[] { myDelegate }); 

Grundsätzlich habe ich eine List<Book>, die ich versuche zu reflektieren und Invoke seine Find Methode. Die Find Methode benötigt eine anstelle von Func<Book, bool>, und ich habe meinen Kopf dafür für ein paar Stunden geschlagen.

Edit: Hier ist der erste Teil der Fehler Spur:

System.MissingMethodException: Constructor on type 'System.Predicate`1[[MyProject.Book, MyProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' not found. 
+0

Wenn jemand das Teil sehen muss, wo ich die Find-Methode aufrufen, kann ich auch, dass liefern, aber ich dachte, dass es von der wesentlich beeinträchtigen würde Teil der Frage. –

Antwort

3

Glücklicherweise ist diese recht einfach zu tun, nur durch Ihren Anruf Expression.Lambda Wechsel:

Type predicateType = typeof(Predicate<>).MakeGenericType(itemType); 
LambdaExpression lambda = Expression.Lambda(predicateType, equality, predParam); 
Delegate compiled = lambda.Compile(); 

Es ist nicht klar, was Du musstest mit dem Ergebnis tun, wohlgemerkt ... wenn die schwach typisierte Version für dich in Ordnung ist, sollte das in Ordnung sein.

+0

Meinst Du Predicate <,> (mit einem Komma)? –

+0

Ich bezweifle es, da es nur 1 Typ arg dauert. :) –

+0

@Jon: Nein. Ich bin mir nicht sicher, welche Version des Codes Sie sah - es ging zumindest ein paar Änderungen, teilweise aufgrund von Inkompetenz und teilweise aufgrund der falsch gelesenen Frage :) –

0

nicht sicher, ob dies ist das gleiche wie Jon Antwort:

public static Predicate<T> GetPredicate<T>() 
{ 
    Type itemType = typeof(T); 
    ParameterExpression predParam = Expression.Parameter(itemType, "p"); 
    Expression left = Expression.Field(predParam, itemType.GetField("AuthorName")); 
    Expression right = Expression.Constant("Jon Skeet", typeof(string)); 
    Expression equality = Expression.Equal(left, right); 
    Func<T, bool> function = (Func<T, bool>)Expression.Lambda(equality, new[] { predParam }).Compile(); 
    return new Predicate<T>(function); 
} 
+0

Sorry, ich habe versucht zu vermitteln, dass ich T nicht explizit liefern muss. Anstatt also Zeile 1 explizit zu schreiben, wäre Type itemType ein Parameter für Ihre Lösung. –