2010-08-16 4 views
5

Je suis en train d'essayer de faire this, mais je ne sais pas ce que sera T, donc je construis des choses en utilisant des arbres de réflexion et d'expression.Convertir func pour prédire en utilisant la réflexion en 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 }); 

Fondamentalement, j'ai un List<Book>, que je suis en train de réfléchir et Invoke sa méthode Find. La méthode Find a besoin d'un Predicate<Book> au lieu de Func<Book, bool>, et je me suis battu la tête contre cela pendant quelques heures.

Edit: Voici la première partie de la trace d'erreur:

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

Si quelqu'un a besoin de voir la partie où j'invoquons la méthode Find, je peux également fournir, mais je pensais que ce serait porter atteinte à l'essentiel partie de la question. –

Répondre

3

Heureusement, c'est assez facile à faire, juste en changeant votre appel à Expression.Lambda:

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

Il est pas clair ce que vous avez besoin de faire avec le résultat, gardez à l'esprit que ... si la version faiblement typée est acceptable pour vous, ça devrait aller.

+0

Vouliez-vous dire à Prédicat <,> (avec une virgule)? –

+0

J'en doute, puisqu'il ne faut que 1 type arg. :) –

+0

@Jon: Non. Je ne suis pas sûr de la version du code que vous avez vu - il a subi au moins quelques modifications, en partie à cause de l'incompétence et en partie à cause d'une mauvaise lecture :) –

0

Je ne sais pas si cela est le même que la réponse de Jon:

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

Désolé, j'ai essayé de dire que je n'ai pas de T à fournir explicitement. Ainsi, au lieu d'écrire explicitement la ligne 1, le type itemType serait un paramètre de votre solution. –

Questions connexes