2010-02-19 13 views
16

Come ottenere "System.Type" del modulo?Come ottenere il tipo del modulo in F #

Per il modulo esempio:

module Foo = 
    let bar = 1 

E questo non funziona:

printfn "%s" typeof<Foo>.Name 

errore è:

The type 'Foo' is not defined 
+1

Essere curiosi qui. Perché dovresti farlo? Sai il nome del modulo, Foo, e non credo che F # abbia la capacità di passare i moduli come valore. Grazie. – nlucaroni

+0

L'esigenza è semplice, ho bisogno di un po 'di automazione. Posso farlo con la riflessione. PowerPack.Metadata consente di scorrere i moduli, ma potrebbe esserci qualcosa di più semplice. –

+0

Ho bisogno di farlo anche per un'API fortemente tipizzata in una libreria che sto scrivendo. – justin

risposta

7

Sarebbe certamente bello avere un operatore di moduleof .. Dato che non ce n'è uno, il modo più semplice per fare ciò che vuoi è probabilmente usare la libreria Metadata in F # PowerPack:

#r "FSharp.PowerPack.Metadata.dll" 
open Microsoft.FSharp.Metadata 

// get .NET assembly by filename or other means 
let asm = ... 

let fasm = FSharpAssembly.FromAssembly asm 
let t = fasm.GetEntity("Foo").ReflectionType 

Purtroppo, questo non funzionerà con gruppi dinamici (come quelli generati tramite F # interattivo). Puoi fare qualcosa di simile usando le chiamate vaniglia System.Reflection, ma questo dipende più da una buona comprensione del modulo compilato che prende il tuo modulo.

+0

Il problema principale è che 'FSharpAssembly.FromAssembly asm' carica tutti i tipi. Riduci anche la sicurezza del tipo. –

+0

@Mike - Non sono sicuro di cosa intendi con "riduci la sicurezza del tipo" ... Non c'è modo di usare un modulo come parametro di tipo generico, quindi dovrai usare una stringa. Questo è sfortunato, ma inevitabile. – kvb

+3

richiede ancora un alimentatore o esiste un modo migliore 5 anni dopo? – Maslow

-1

nome modulo non è un tipo.

List in List.map e let (a:List<int>) = [1;2;3] sono diversi.

Il primo List è un nome di modulo, il secondo è un tipo.

+5

Sono preoccupato per "FSharpType.IsModule (System.Type)", quindi il tipo di modulo IS, almeno nei termini CLR. –

+1

Il nome della classe statica (tipo) a cui è compilato il modulo 'List' è probabilmente' ListModule'. –

26

Si potrebbe aggiungere un tipo di marcatore al modulo e quindi scoprire il tipo di modulo da quella:

module Foo = 
    type internal Marker = interface end 
    let t = typeof<Marker>.DeclaringType 
5

Può anche essere fatto utilizzando Quotations. In primo luogo, definire questa funzione di supporto da qualche parte:

open Microsoft.FSharp.Quotations.Patterns 

let getModuleType = function 
| PropertyGet (_, propertyInfo, _) -> propertyInfo.DeclaringType 
| _ -> failwith "Expression is no property." 

Quindi, è possibile definire un modulo e ottenere il suo tipo come questo:

module SomeName = 
    let rec private moduleType = getModuleType <@ moduleType @> 

Spero che questo aiuti.

+0

Questo non funziona in modo interattivo, giusto? – BitTickler

+0

Lo fa per me, anche se ho modificato la seconda parte in: 'module SomeName = lascia rec moduleType = getModuleType <@ moduleType @> ;;, quindi' SomeName.moduleType ;; 'deve restituire le informazioni sul tipo. –

Problemi correlati