Let's say I have a Foo.fsx
script that contains this code:
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
How can I achieve that? Thanks!
This is a tricky question, because F# interactive compiles all types into types with some mangled names (and the executing assembly can contain multiple versions of the same type).
I managed to do it using a simple trick - you'd add an additional type to the module - then you can use typeof<..>
to get information about this type. The type inside a module is compiled as a nested type, so you can get the name of the type representing the module from this (nested) type:
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, [| |])
You could probably simply search all types in the assembly looking for +Bar
. That would work as well. The benefit of the trick above is that you get a reference to the specific version of the type (if you interactively run the code multiple times, you'll get a reference to the module corresponding to the current Bar.A
type)
As a side-note, there were some discussions about supporting moduleof<Bar>
(or something like that) in future versions of F# - this is a bit inelegant as it is not a real function/value like typeof
, but it would very useful!