Convertir func a predicar usando reflexión en C #

c# expression-trees predicate reflection

Pregunta

Básicamente estoy tratando de hacer esto , pero no sé qué será T, así que estoy construyendo cosas utilizando los árboles de Reflexión y Expresión.

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

Básicamente, tengo una List<Book> , en la que estoy tratando de reflexionar e Invoke su método de Find . El método Find necesita un Predicate<Book> lugar de Func<Book, bool> , y he estado golpeando mi cabeza contra esto durante algunas horas.

Edición: Aquí está la primera parte de la traza de error:

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

Respuesta aceptada

Afortunadamente, esto es bastante fácil de hacer, simplemente cambiando su llamada a Expression.Lambda :

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

No está claro lo que tenía que hacer con el resultado, no importa si la versión de tipo débil está bien para usted, eso debería estar bien.


Respuesta popular

No estoy seguro si esto es lo mismo que la respuesta 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);
}


Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow