从函数参数中检索属性

时间:2011-05-04 09:28:36

标签: reflection f# attributes

如果我有一个函数接受另一个函数:

[<SomeAttribute()>]
let f (g:unit->unit) =
    //Want to get g's custom attributes

如何从f?

访问g的自定义属性

我想我错过了一些非常明显的东西。

2 个答案:

答案 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())