尝试从程序集中检索 nunit 测试属性时出现错误 FS0001 或 FS0041

errors FS0001 or FS0041 while attempting to retrieve nunit test attributes from an assembly

下面的 F# 脚本因 FS0041 失败(无法根据此程序点之前的类型信息确定方法 'GetCustomAttributes' 的唯一重载。可能需要类型注释)。你是怎么解决的?

如果我添加类型注释,例如

let getattr (el : Sometype) = Attribute.CustomAttributes(el, true)

它因 FS0001 而失败(类型 'Sometype' 与类型 'Assembly' 不兼容。 可能过载:...省略长行...)

open System
open System.Reflection

let nunit_tattr = typeof<NUnit.Framework.TestFixtureAttribute>
let getattr el = Attribute.GetCustomAttributes(el, true)
let _ =
    let asm = Assembly.LoadFile("some_asm_that_contains_nunit_tests.dll")
    let ttypes = asm.GetTypes()
    let allattrs = Seq.map getattr ttypes
    printf "%A\n" allattrs

另一方面,在 REPL 中我更进一步。

    > let z  = ttypes.[0];;

    val z : Type = Foo.Bar.Cow.Test.AaaTest

    > Attribute.GetCustomAttributes(z, true);;
    val it : Attribute [] =
    [|NUnit.Framework.TestFixtureAttribute
        {Arguments = [||];
         Categories = null;
         Category = null;
         Description = null;
         Ignore = false;
         IgnoreReason = null;
         TypeArgs = [||];
         TypeId = NUnit.Framework.TestFixtureAttribute;}|]

本练习的目的是过滤掉没有 NUnit.Framework.TestFixtureAttribute 的方法(该代码未显示)。 ttypes 中的数组元素是异构的,例如上面显示的索引 0 具有类型 Foo.Bar.Cow.Test.AaaTest 但索引 1 具有类型 Foo.Bar.Cow.Test.BbbTest,等等

像这样启动fsharpi

    fsharpi /r:/usr/lib/cli/nunit.framework-2.6/nunit.framework.dll

我认为您需要仔细阅读反射以及 Type 类型实际代表什么。

入门 - 如果您想获取具有特定属性的类型,请查看此脚本:

open System
open System.Reflection

/// an attribute and some types to test it on
type ExampleAttribute () = 
   inherit Attribute ()

[<Example>] type A = A
type B = B    
[<Example>] type C = C

/// get the types in an assembly
let types = Assembly.GetExecutingAssembly().GetTypes()

/// filter the types that are marked with ExampleAttribute (gives you A and C)
types 
|> Array.filter (fun typ -> typ.IsDefined(typeof<ExampleAttribute>))

请注意 typeof 运算符 - 这是从静态类型名称(代码中的 ExampleAttribute 字符串)到 Type 类型对象的方法,后者是 ExampleAttribute 的运行时表示类型。