In C#, use reflection to convert a function to a predicate.

c# expression-trees predicate reflection

Question

Since I don't know what T will be, I'm simply attempting to accomplish this while utilizing reflection and expression trees to build things up.

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

In essence, I have aList<Book> which I'm attempting to consider andInvoke its Find method. TheFind technique requires aPredicate<Book> in place ofFunc<Book, bool> , and I've spent a couple hours banging my head against this.

The first section of the error trace is as follows:

System.MissingMethodException: Constructor on type 'System.Predicate`1[[MyProject.Book, MyProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' not found.
1
5
5/23/2017 12:15:47 PM

Accepted Answer

Fortunately, doing this is rather simple. You just need to change your call toExpression.Lambda :

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

Even though it's unclear what you were supposed to do with the outcome, if the weakly-typed version is acceptable to you, it should be alright.

3
8/16/2010 4:51:24 PM

Popular Answer

I'm not sure whether this corresponds to Jon's response:

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


Related Questions





Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow