Rei*_*aka 1 reflection f# attributes
如果我有一个函数接受另一个函数:
[<SomeAttribute()>]
let f (g:unit->unit) =
//Want to get g's custom attributes
Run Code Online (Sandbox Code Playgroud)
如何从f访问g的自定义属性?
我想我错过了一些非常明显的东西.
这通常不可能,因为当您使用函数作为参数(例如f foo)时,F#编译器将foo值包装到某个对象中.foo从这个对象中提取实际的方法引用将非常困难(并且只有在编译器没有进行一些优化时才会起作用).
但是,您可以使用F#引用获得所需的行为.unit -> unit你f可以采用引用函数代替函数Expr<unit -> unit>.然后你可以使用f <@ foo @>函数调用函数,函数可以提取方法参考并调用foo.
这是一个例子.它需要引用F#PowerPack(以便它可以评估报价).在这个简单的案例中,评估应该非常有效:
#r @"FSharp.PowerPack.Linq.dll"
type SomeAttribute(name:string) =
inherit System.Attribute()
member x.Name = name
// Example function with some attribute
[<SomeAttribute("Test")>]
let g () = printfn "Hello"
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Linq.QuotationEvaluation
// Takes a quotation instead of a function value
let f (g:Expr<unit->unit>) =
// Extract method info & attributes from the quotation
match g with
| DerivedPatterns.Lambdas(_, Patterns.Call(_, mi, _)) ->
let attrs = mi.GetCustomAttributes(typeof<SomeAttribute>, false)
for a in attrs |> Seq.cast<SomeAttribute> do
printfn "%A" a.Name
| _ ->
failwith "Argument must be of the form <@ foo @>!"
// Compile the function so that it can be executed (the compilation
// takes some time, but calling invoke should be fast)
let invoke = g.Compile()()
invoke()
invoke()
// And this is how you call the function
f <@ g @>
Run Code Online (Sandbox Code Playgroud)