gpt4 book ai didi

C# 使用 Expression.Call 构造 lambda 不喜欢某些类型作为参数?

转载 作者:行者123 更新时间:2023-11-30 22:41:27 26 4
gpt4 key购买 nike

出于各种原因,我正在使用表达式树工具动态构建 C# lambda。例如我可以在运行时创建一个 Func ,如以下代码片段所示。

   public static bool myMethod( object obj ) {  … }

// Construct a Func<string,bool>
var myMethod = GetType().GetMethod("myMethod");
var lambdaParams = new ParameterExpression[] {Expression.Parameter(typeof (string))};
var callMyMethod = Expression.Call(myMethod, lambdaParams);
var lambda = Expression.Lambda(typeof(Func<string,bool>), callMyMethod, lambdaParams);
var del = (Func<string,bool>)lambda.Compile();
del("foo"); // works

但是,如果我使用相同的代码尝试制作 Func 或 Func ,它会在指示的地方爆炸,并出现以下奇怪的异常:

    // Construct a Func<DateTime,bool> or perhaps a struct type fails... why?
var myMethod = GetType().GetMethod("myMethod");
var lambdaParams = new ParameterExpression[] {Expression.Parameter(typeof (DateTime))};
var callMyMethod = Expression.Call(myMethod, lambdaParams); // Blows up here…

System.ArgumentException: Expression of type 'System.DateTime' cannot be used for parameter of type 'System.Object' of method 'Boolean myMethod(System.Object)'

因此,string 有效,List 有效,但 int32 无效,DateTime 也无效。到底是怎么回事?我不知道 C# 的深层内部结构是如何工作的,但我猜这是因为 int 真的被当作原始数据处理,也许还有 DateTime(作为结构)......

如有任何帮助,我们将不胜感激。

谢谢,帕特

最佳答案

据我所知,Expression.Call 不执行值类型参数的自动装箱。我找不到这方面的任何文档,但在 this forum page 中提到了它.

一种解决方法是在表达式中使用 Expression.TypeAs 显式进行装箱转换.

Creates a UnaryExpression that represents an explicit reference or boxing conversion where null is supplied if the conversion fails.

在您的情况下,这应该可行:

var boxedParams = lambdaParams.Select(p => Expression.TypeAs(p, typeof(object)))
.ToArray();

var callMyMethod = Expression.Call(myMethod, boxedParams);

(如果只有一个参数,则不需要花哨的 lambda)

根据实际使用情况,您可能需要根据所讨论的类型是否为值类型来检查是否需要装箱转换。

关于C# 使用 Expression.Call 构造 lambda 不喜欢某些类型作为参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4813036/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com