F#Dynamic Eval,Reflection,IL

时间:2012-11-21 08:05:50

标签: reflection f# cil

由于我似乎花了95%的编码时间实际上在F#的FSI中,我绕道而行(参见:分心)并且想要编写一些实用函数。

我感兴趣的特定实用程序是一个'反汇编'(http://www.cons.org/cmucl/doc/reading-disassembly.html)函数,它可以为给定函数转储IL,稍后可能计数指令,基本静态分析等,一般这只是分心天堂。我已经编写了代码来将byteArrayIL映射到MSIL名称(几乎)。

以下是用于从当前模块获取函数名称的片段:

let dec_c = MethodBase.GetCurrentMethod().DeclaringType

System.Reflection.Assembly.GetAssembly(dec_c).GetTypes() 
|> Seq.map (fun x -> x.FullName) //, get_function_instructions x)

这很有效,因为x.FullName反映了实际的函数名称:

FSI_0001
<StartupCode$FSI_0001>.$FSI_0001
FSI_0002
FSI_0002+instructions_of_bytes@24
FSI_0002+remove_null_function_body_bytes@32
FSI_0002+remove_null_function_body_bytes@31-1
FSI_0002+resolve_IL_from_bytes@38
FSI_0002+resolve_IL_from_bytes@36-1
FSI_0002+it@49
FSI_0002+it@50-1
<StartupCode$FSI_0002>.$FSI_0002
FSI_0003
FSI_0003+it@49-2
FSI_0003+it@50-3
<StartupCode$FSI_0003>.$FSI_0003

因此我们可以根据函数名称轻松编写一个函数进行过滤。

不幸的是(可能是由于我的误解),似乎并非所有函数都以这种方式可用,例如,如果我们定义以下简单函数然后重新运行转储:

(* reload FSI *)
let simple_add x = x + 1
(* rerun the function name dumping *)

FSI_0001
<StartupCode$FSI_0001>.$FSI_0001
FSI_0002
FSI_0002+instructions_of_bytes@24
FSI_0002+remove_null_function_body_bytes@32
FSI_0002+remove_null_function_body_bytes@31-1
FSI_0002+resolve_IL_from_bytes@38
FSI_0002+resolve_IL_from_bytes@36-1
FSI_0002+it@50
FSI_0002+it@51-1
<StartupCode$FSI_0002>.$FSI_0002

奇怪的是,结果文本中没有'simple_add'函数。

思想:     1.也许函数simple_add不会被反射实现,直到看到它被使用?听起来很奇怪。     2.可能是其中一个“FSI_0002 + it”字符串实际上就是我们的功能。

问题:     1.为什么输出不反映所有函数名称?     2.有更好的方法吗?

1 个答案:

答案 0 :(得分:3)

我觉得我已经睡了一半(半睡觉)答案,我错了,没有必要列出每个函数的字符串名称......

let get_function_instructions (mb : System.Type) = 
  mb.GetMethods() 
  |> Seq.map ...

let find_func_print_instructions f =
  f.GetType()
  |> get_function_instructions 
  |> print_instruction_text