避免需要在代碼中明確寫入測試名稱(作爲字符串)的一種方法是使用引號。您可以創建一個「帶引號」的函數值列表,而不是創建函數列表和字符串列表。然後,您可以編寫處理引文的代碼,併爲您提供所需的一切。
我假設你的測試看起來大致如下(函數取單位並返回一些值作爲結果)。該列表將被構造如下:
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