由于我似乎花了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.有更好的方法吗?
答案 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