F# ASP.NET Core极简Web API:未用lambda时端点为何忽略参数名?
问题解决:F# Web API中直接传递函数丢失参数名的问题
问题原因
F#编译顶级函数(如let add x y)时,默认不会将参数名x、y嵌入到元数据中。当你把这类函数直接包装成Func<_,_,_>时,ASP.NET Core无法从元数据中读取原始参数名,只能使用框架默认的delegateArg0、delegateArg1作为参数键。
而lambda表达式(fun x y -> add x y)在编译时,编译器会自动为生成的Func实例的Invoke方法保留参数名元数据,因此ASP.NET Core能识别并使用x、y作为参数名。
无需lambda/控制器的解决方案
给函数的每个参数添加[<ParameterName>]属性(来自System.Runtime.CompilerServices命名空间),强制编译器将参数名写入元数据:
open System.Runtime.CompilerServices // 为参数显式指定元数据中的名称 let add ([<ParameterName("x")>] x: int) ([<ParameterName("y")>] y: int) = x + y // 直接传递函数,参数名会被ASP.NET Core识别 app.MapGet("addFixed", Func<int, int, int>(add))
现在访问addFixed端点时,就可以使用https://localhost:7129/addFixed?x=3&y=4这样的参数名了。
补充说明
你提到反射时看到两者的Invoke方法参数名都是x和y,这是因为反射工具可能显示的是IL层面的参数名,而非元数据中保留的原始参数名。顶级函数的IL参数名可能被编译器优化,而lambda生成的Func的Invoke方法会保留显式的参数名元数据,这才是ASP.NET Core识别参数名的依据。
内容的提问来源于stack exchange,提问作者Overlord Zurg
相关产品推荐
相关产品推荐

