【问题标题】:Get type of a module at compile time in F#在 F# 的编译时获取模块的类型
【发布时间】:2018-07-20 11:57:53
【问题描述】:

我们知道,在 C# 中,我们可以在编译时使用 typeof(OutType) 获取类型的类型,这让我们可以稍后将其传递给属性,因为它是常量表达式。

我看到了this 的问题,但它并没有真正解决编译时间的使用问题。

所以我的问题是:有没有办法在 F# 标准库中以编译类型获取给定模块的System.Type

【问题讨论】:

  • 您为什么要专门这样做?我理解你为什么需要编译时间常数的部分,但我不明白一旦你掌握了模块的运行时类型,你会做什么。
  • 我的情况是我需要它来提供给 NUnit 的 TestCaseSource 属性重载
  • 可以在编译时获取它的类型吗?

标签: f# compile-time-constant


【解决方案1】:

F# 在设计上不允许使用其typeof 运算符获取模块的类型,因为它们不是该语言中的一流概念。

来自spec,第 13.2 节:

编译 F# 模块以提供相应的编译 CLI 类型声明和 System.Type 对象,尽管使用 typeof 无法访问 System.Type 对象 操作员。

但是,模块编译为静态类,因此可以在运行时使用反射获取类型(这就是 typeof<MyModule.Dummy>.DeclaringType 示例中发生的情况),并且可以获取在引用的 F# 程序集中定义的模块的类型在 C# 中使用 typeofoperator。

对于你想要做的事情,你最好使用类而不是模块,因为这样你就可以毫不费力地掌握类型:

type MyFactoryClass = 
    static member TestCases = [ 1; 2; 3 ]

...

[<Test; TestCaseSource(typeof<MyFactoryClass>, "TestCases">] 
let test (arg: int) = ...

【讨论】:

  • 我知道我可以那样做,所以我从来没有坚持我的具体案例的答案,而是如果在 F# 中与 C# 的 typeof 有 1:1 等效
  • 谢谢老兄,TestCaseSource 的使用成功了。
【解决方案2】:

如果您可以在该模块中引用一个类型(或者如果没有类型,则创建一个虚拟类型),您可以这样做:

module MyModule =
    type Dummy = Dummy

let myModule = typeof<MyModule.Dummy>.DeclaringType

【讨论】:

  • .DeclaringType 的使用意味着它不是编译时间常数(也就是说,您不能将它用作属性构造函数的参数)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-20
  • 2016-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多