如果我有一个函数接受另一个函数:
[<SomeAttribute()>]
let f (g:unit->unit) =
//Want to get g's custom attributes
如何从f?
访问g的自定义属性我想我错过了一些非常明显的东西。
答案 0 :(得分:5)
这通常不可能,因为当您使用函数作为参数(例如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 @>
答案 1 :(得分:0)
let f (g:unit->unit) =
printfn "%d" (g.GetType().GetCustomAttributes(true).Count())