2011-05-04 87 views
1

如果我有一個函數,在另一個功能:從函數參數檢索屬性

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

我如何可以訪問F G的自定義屬性?

我想我在這裏錯過了一些非常明顯的東西。

+0

非常類似的問題:http://stackoverflow.com/questions/1575180/retrieve-methodinfo-of-af-function(你想要什麼不似乎是可能的,除非你知道裝配和功能的名稱。) – wmeyer 2011-05-04 10:13:06

+0

啊,謝謝。我想知道是否應該關閉/刪除這個問題,因爲它顯然是重複的? – 2011-05-04 10:15:14

+0

我認爲你可以接受Tomas的答案。我也使用相同的方法(在嘗試破解CIL後,CIL在發佈模式下不起作用)。 – Stringer 2011-05-04 14:10:14

回答

4

這不是一般的可能,因爲當使用函數作爲參數(例如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 @> 
+0

很酷的作品,謝謝! – 2011-05-04 20:12:29

0
let f (g:unit->unit) = 
    printfn "%d" (g.GetType().GetCustomAttributes(true).Count()) 
+0

我認爲這會返回類型屬性而不是實例屬性(例如ReflectedDefinition不會出現)。 – 2011-05-04 10:03:53

+0

是的,這並不完全。嗯.... – 2011-05-04 10:05:13