假设我正在F#中创建一个属性,并将其应用于函数,如下所示:
type MyAttribute(value: int) =
inherit System.Attribute()
member this.Value = value
[<My(42)>]
let myFunction() = ()
如何通过反射检索该属性?
理想情况下,我想使用一些类似的东西,myFunction.GetType().GetCustomAttributes(true)
但这是行不通的。
myFunction.GetType()
之所以不起作用,是因为FSharpFunc<_,_>
每次你引用一个函数时,F#编译器都会自动创建一个子类。你将获得的类型FSharpFunc
,这不是你所需要的。
要获取函数的反射信息,你需要先找到该函数所在的模块。每个模块都被编译成一个静态类,你可以在该类中找到该函数。因此,要获得此功能:
module MyModule
let myFunc x = x + 1
你需要执行以下操作(我没有检查代码):
// Assuming the code is in the same assembly as the function;
// otherwise, you must find the assembly in which the module lives
let assm = System.Reflection.Assembly.GetExecutingAssembly()
let moduleType = assm.GetType("MyModule")
let func = moduleType.GetMethod("myFunc")
let attrib = func.GetCustomAttribute<MyAttribute>()
那讲得通。有没有办法在运行时做到这一点?我可以
FSharpFunc
在某种情况下从实例回到模块,而不是在构建时从模块名称出发吗?如果有一个好的方法,我不知道。您总是可以获取
Invoke
方法的主体IL,并通过它查找它所调用的函数,但这不如解决方案获得的好。