如何在fsx文件中键入模块?

时间:2010-05-26 19:55:46

标签: reflection f# f#-interactive

假设我有一个包含此代码的Foo.fsx脚本:

module Bar =
  let foobar = "foo"+"bar"

open Bar
let a = System.Reflection.Assembly.GetExecutingAssembly()
let ty = a.GetType("Foo.Bar") // but it returns null here

我怎样才能实现这一目标?谢谢!

1 个答案:

答案 0 :(得分:4)

这是一个棘手的问题,因为F#interactive将所有类型编译成具有一些受损名称的类型(并且执行程序集可以包含相同类型的多个版本)。

我设法使用一个简单的技巧 - 你可以为模块添加一个额外的类型 - 然后你可以使用typeof<..>来获取有关此类型的信息。模块内部的类型被编译为嵌套类型,因此您可以从此(嵌套)类型获取表示模块的类型的名称:

module Bar = 
  let foobar = "foo"+"bar" 
  type A = A

// Get type of 'Bar.A', the name will be something like "FSI_0001+Bar+A",
// so we remove the "+A" from the name and get "FSI_0001+Bar"
let aty = typeof<Bar.A>
let barName = aty.FullName.Substring(0, aty.FullName.Length - "+A".Length)
let barTy = aty.Assembly.GetType(barName)

// Get value of the 'foobar' property - this works!
barTy.GetProperty("foobar").GetValue(null, [| |])

您可以简单地搜索程序集中查找+Bar的所有类型。那也行。上述技巧的好处是您可以获得对该类型的特定版本的引用(如果您以交互方式多次运行代码,您将获得对应于当前Bar.A类型的模块的引用)< / p>

作为旁注,在F#的未来版本中有一些关于支持moduleof<Bar>(或类似的东西)的讨论 - 这有点不优雅,因为它不是真正的函数/值,如{{1但是它会非常有用!