避免需要在代码中明确写入测试名称(作为字符串)的一种方法是使用引号。您可以创建一个“带引号”的函数值列表,而不是创建函数列表和字符串列表。然后,您可以编写处理引文的代码,并为您提供所需的一切。
我假设你的测试看起来大致如下(函数取单位并返回一些值作为结果)。该列表将被构造如下:
let test_a() = Some 32
let test_b() = None
let tests = [ <@ test_a @>; <@ test_b @> ]
然后,你可以写这样的代码来获取有关考试的信息:
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.Patterns
let getInfo (e:Expr<unit -> 'R>) = // '
match e.Raw with
// This expects that the quotation contains a reference to a global
// function (in some module) that takes unit as the parameter
| Lambda(a, Call(_, m, _)) ->
// Return a tuple containing a name of the test (string) and
// a function that invokes it (note that the invocation will be
// a bit slow as we use reflection here)
m.Name, (fun() -> m.Invoke(null, [| |]) :?> 'R) // ' (*)
// Ohter quotations will cause an exception
| _ -> failwith "unexpected quotation"
下面是一个例子,你将如何使用:
或者,您可以修改行(*)
以生成一个函数,该函数返回测试名称和结果,从而不需要Option.map
:
// An alternative version of the marked line in the 'getInfo' function
(fun() -> m.Name, m.Invoke(null, [| |]) :?> 'R) // ' (*)
// Then you can write just:
tests |> List.map getInfo |> List.tryPick (fun test -> test())
谢谢。它使我花了一段时间才明白,但我得到了它的工作。对于那些将来查看答案的人,考虑到我编辑了问题,“备选”之后的部分目前无效。 – 2010-07-05 10:46:29