以编程方式用装饰器包装所有模块的函数

时间:2014-02-03 05:19:33

标签: f# wrapper decorator trace

需要跟踪。装饰器应该打印函数名称,参数值和返回值。不是每次都为每个函数编写一个装饰器,如果能够以编程方式执行此操作,那将是非常棒的。

2 个答案:

答案 0 :(得分:3)

可以使用MethodBase.GetCurrentMethod反射来发现当前函数名称。可以使用内联函数轻松修饰函数以进行日志记录:

let inline log args f  =
  let mi = System.Reflection.MethodBase.GetCurrentMethod()
  let result = f ()
  printf "%s %A -> %A" mi.Name args result

let add a b = log (a,b) (fun () -> a + b)

add 1 1

打印:add (1, 1) -> 2

编辑:另一种选择是创建一个包裹函数,即:

let inline wrap f = 
  fun ps ->
    let result = f args
    printfn "%A -> %A" args result
    result

let add (a,b) = a + b

wrap add (1,1)

但是在这种情况下,没有一种简单的方法可以以编程方式检索函数名称。

另一种选择可能是开发一个类型提供程序,它将程序集路径作为参数并提供所有成员的包装版本。

答案 1 :(得分:2)

我之前有同样的愿望,发现目前没有F#的自动化解决方案。

请参阅:Converting OCaml to F#: Is there a simple way to simulate OCaml top-level #trace in F#

虽然OCaml的时间旅行跟踪设施是最有用的调试功能,但它并不是一个完美的选择。但是当我使用OCaml时,它是我使用的第一个检测工具。

请参阅:Using PostSharp with F# - Need documentation with working example

使用AOP即PostSharp的建议也是另一个好建议,因为PostSharp的首席工程师Gael Fraiteur的回应指出:

  

PostSharp并未正式支持F#。

除了使用Phillip Trelford所建议的反射,我还没有尝试过,我找到的最佳解决方案是手动修改每个要跟踪的函数,如我在Converting OCaml to F#: Is there a simple way to simulate OCaml top-level #trace in F#中所述并保存结果使用NLog到单独的日志文件。

请参阅:Using NLog with F# Interactive in Visual Studio - Need documentation

另一个追求的途径是检查F# on Mono的工作,因为在那里做了很多工作来添加额外的工具以供F#使用。

  

基本上我发现的是,因为我的F#技能增加了我的需求   使用调试器或跟踪减少。

目前,当我遇到需要此级别检查的问题时,添加Converting OCaml to F#: Is there a simple way to simulate OCaml top-level #trace in F#中所述的检查代码有助于解决我的误解。

同样值得注意的是,从C#世界到F#世界的人们往往希望调试器同样有用。请记住,命令式语言倾向于操纵变量中保存的数据,并且调试器用于检查这些变量中的值,而使用函数式编程,至少对我来说,我试图避免可变值,因此只需要一个值检查是传递给函数的值而没有其他值,从而减少或消除了对问题函数之外的调试器或检查的需要。