在 C# 中使用反射将 func 转换为谓词

发布于 2024-09-14 12:54:01 字数 1535 浏览 8 评论 0原文

我基本上试图做这个,但我不这样做知道 T 是什么,所以我使用反射树和表达式树来构建东西。

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

基本上,我有一个 List,我试图对其进行反思并Invoke 它的 Find 方法。 Find 方法需要一个 Predicate 而不是 Func,我一直在努力反对这一点几个小时。

编辑:这是错误跟踪的第一部分:

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

I'm basically trying to do this, but I don't know what T will be, so I'm building things up using Reflection and Expression trees.

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

Basically, I have a List<Book>, which I'm trying to reflect on and Invoke its Find method. The Find method needs a Predicate<Book> instead of Func<Book, bool>, and I've been beating my head against this for a few hours.

Edit: Here is the first part of the error trace:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

无语# 2024-09-21 12:54:01

幸运的是,这很容易做到,只需更改对 Expression.Lambda 的调用即可:

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

目前尚不清楚您需要对结果做什么,请注意...如果弱类型版本没问题的话对你来说,那应该没问题。

Fortunately this is pretty easy to do, just by changing your call to Expression.Lambda:

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

It's not clear what you needed to do with the result, mind you... if the weakly-typed version is okay for you, that should be fine.

若无相欠,怎会相见 2024-09-21 12:54:01

不确定这是否与乔恩的回答相同:

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

Not sure if this is the same as Jon's answer:

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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文