2

We know that in C# we can get type of a type at compile time using typeof(OutType) this lets us pass this to attributes later as it is constant expression.

I saw this question, but it doesn't really address the compile time usage.

So my question is: Is there a way to get System.Type of a given module at compile type within F# standard library?

kuskmen
  • 3,648
  • 4
  • 27
  • 54
  • Why are you trying to do that specifically? I understand the part why you need a compile time constant, but I don't understand what would you do once you got hold of the module's runtime type. – scrwtp Jul 20 '18 at 21:51
  • I my case I need it to supply it to NUnit’s TestCaseSource attribute overload – kuskmen Jul 20 '18 at 21:53
  • Can I obtain its type at compile time? – kuskmen Jul 20 '18 at 22:05

2 Answers2

2

F# disallows obtaining a module's type using its typeof operator by design, as they're not first-class concepts in the language.

From the spec, section 13.2:

F# modules are compiled to provide a corresponding compiled CLI type declaration and System.Type object, although the System.Type object is not accessible by using the typeof operator.

Modules compile to static classes however, so it is possible to obtain the type at runtime using reflection (and that's what happens in typeof<MyModule.Dummy>.DeclaringType example), and it's possible to obtain the type of a module defined in a referenced F# assembly using typeofoperator in C#.

For what you're trying to do, you'd best use a class instead of a module, because then you can get hold of the type without hassle:

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

...

[<Test; TestCaseSource(typeof<MyFactoryClass>, "TestCases">] 
let test (arg: int) = ...
scrwtp
  • 13,437
  • 2
  • 26
  • 30
  • I know I can do it like that, thats ehy I never insisted in my answer about my specific case but rather if there is 1:1 equivalent in F# to C#’s typeof – kuskmen Jul 20 '18 at 22:28
  • Thanks mate, this usage of `TestCaseSource` succeeded. – kuskmen Jul 23 '18 at 09:43
1

If you are OK to refer to a type inside that module (or create a dummy one if there are no types), you could do this:

module MyModule =
    type Dummy = Dummy

let myModule = typeof<MyModule.Dummy>.DeclaringType
TheQuickBrownFox
  • 10,544
  • 1
  • 22
  • 35
  • Usage of `.DeclaringType` means that's not a compile time constant however (that is, you can't use that as an argument to an attribute constructor). – scrwtp Jul 20 '18 at 21:47