从函数中提取函数名称

时间:2016-03-31 04:43:52

标签: c# reflection f#

如何创建一个名为getFuncName的函数,它接受类型函数(unit - >'a)并返回其名称。

我正在与其中一个C#开发人员交谈,他们说你可以在Func类型上使用.Method属性,如示例 here所示。

我尝试将其转换为F#:

例如将(单位 - >'a)转换为类型Func< _>然后在它上面调用属性,但它总是返回字符串“Invoke”。

let getFuncName f =
    let fFunc = System.Func<_>(fun _ -> f())
    fFunc.Method.Name

let customFunc() = 1.0

// Returns "Invoke" but I want it to return "customFunc"
getFuncName customFunc

这个问题的一些背景是:

我创建了一个类型为(unit - &gt; Deedle.Frame)的函数数组。我现在想循环调用它们的那些函数并将它们保存到csv,其中csv名称与函数同名。一些假设代码如下:

let generators : (unit -> Frame<int, string>) array = ...

generators
|> Array.iter (fun generator -> generator().SaveCsv(sprintf "%s\%s.csv" __SOURCE_DIRECTORY__ (getFuncName generator)))

这用于脚本意义而不是应用程序代码。

1 个答案:

答案 0 :(得分:1)

不确定您是如何搜索信息的,但是对搜索引擎的第一个查询给了我这样的回复:

let getFuncName f =
   let type' = f.GetType()
   let method' = type'.GetMethods() |> Array.find (fun m -> m.Name="Invoke")

   let il = method'.GetMethodBody().GetILAsByteArray()
   let methodCodes = [byte OpCodes.Call.Value;byte OpCodes.Callvirt.Value]

   let position = il |> Array.findIndex(fun x -> methodCodes |> List.exists ((=)x))
   let metadataToken = BitConverter.ToInt32(il, position+1) 

   let actualMethod = type'.Module.ResolveMethod metadataToken
   actualMethod.Name
  

不幸的是,这段代码仅在F#编译器没有将函数体内联到调用方法时才有效。

取自here

虽然可能有更简单的方法。