Reflection 从函数参数检索属性

Reflection 从函数参数检索属性,reflection,f#,attributes,Reflection,F#,Attributes,如果我有一个函数包含另一个函数: [<SomeAttribute()>] let f (g:unit->unit) = //Want to get g's custom attributes [] 设f(g:单位->单位)= //想要获得g的自定义属性吗 如何从f访问g的自定义属性 我想我在这里遗漏了一些非常明显的东西。这在一般情况下是不可能的,因为当您使用函数作为参数(例如f foo)时,f编译器会将foo值包装到某个对象中。从这个对象中提取实际的方法引用foo将

如果我有一个函数包含另一个函数:

[<SomeAttribute()>]
let f (g:unit->unit) =
    //Want to get g's custom attributes
[]
设f(g:单位->单位)=
//想要获得g的自定义属性吗
如何从f访问g的自定义属性


我想我在这里遗漏了一些非常明显的东西。

这在一般情况下是不可能的,因为当您使用函数作为参数(例如
f foo
)时,f编译器会将
foo
值包装到某个对象中。从这个对象中提取实际的方法引用
foo
将是非常困难的(并且只有在编译器没有进行一些优化的情况下,它才会工作)

let f (g:unit->unit) =
    printfn "%d" (g.GetType().GetCustomAttributes(true).Count())
但是,您可以使用F#引号获得所需的行为。您的
f
可以使用带引号的函数
Expr unit>
,而不是使用函数
unit->unit
。然后,您可以使用
f
调用该函数,该函数可以提取方法引用,还可以调用
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 @>
#r@“FSharp.PowerPack.Linq.dll”
键入SomeAttribute(名称:string)=
继承System.Attribute()
成员x.名称=名称
//具有某些属性的示例函数
[]
设g()=printfn“Hello”
打开Microsoft.FSharp.quotes
打开Microsoft.FSharp.Linq.QuotationEvaluation
//采用引号而不是函数值
设f(g:Exprunit>)=
//从报价单中提取方法信息和属性
匹配
|DerivedPatterns.Lambdas(,Patterns.Call(,mi,))->
设attrs=mi.GetCustomAttributes(typeof,false)
对于属性中的a |>顺序cast do
printfn“%A”A.名称
| _ -> 
failwith“参数的形式必须相同!”
//编译函数以使其可以执行(编译
//需要一些时间,但调用invoke应该很快)
让invoke=g.Compile()()
调用()
调用()
//这就是调用函数的方式
F

这通常是不可能的,因为当您使用函数作为参数时(例如
f foo
),f#编译器将
foo
值包装到某个对象中。从这个对象中提取实际的方法引用
foo
将是非常困难的(并且只有在编译器没有进行一些优化的情况下,它才会工作)

但是,您可以使用F#引号获得所需的行为。您的
f
可以使用带引号的函数
Expr unit>
,而不是使用函数
unit->unit
。然后,您可以使用
f
调用该函数,该函数可以提取方法引用,还可以调用
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 @>
#r@“FSharp.PowerPack.Linq.dll”
键入SomeAttribute(名称:string)=
继承System.Attribute()
成员x.名称=名称
//具有某些属性的示例函数
[]
设g()=printfn“Hello”
打开Microsoft.FSharp.quotes
打开Microsoft.FSharp.Linq.QuotationEvaluation
//采用引号而不是函数值
设f(g:Exprunit>)=
//从报价单中提取方法信息和属性
匹配
|DerivedPatterns.Lambdas(,Patterns.Call(,mi,))->
设attrs=mi.GetCustomAttributes(typeof,false)
对于属性中的a |>顺序cast do
printfn“%A”A.名称
| _ -> 
failwith“参数的形式必须相同!”
//编译函数以使其可以执行(编译
//需要一些时间,但调用invoke应该很快)
让invoke=g.Compile()()
调用()
调用()
//这就是调用函数的方式
F

我认为这会返回类型属性而不是实例属性(例如,ReflectedDefinition不会出现)。我认为这会返回类型属性而不是实例属性(例如,ReflectedDefinition不会出现)。非常类似的问题:(除非你知道程序集和函数名,否则你想要的似乎是不可能的。)啊,谢谢。我不知道我是否应该关闭/删除这个问题,因为它显然是重复的?我想你可以接受Tomas的答案。我也在使用同样的方法(在尝试破解CIL后,它在发布模式下不起作用).非常相似的问题:(除非你知道程序集和函数名,否则你想要的似乎是不可能的。)啊,谢谢。我想我是否应该关闭/删除这个问题,因为它显然是重复的?我想你可以接受Tomas的答案。我也在使用同样的方法(在尝试破解CIL后,它在发布模式下不工作)。