2010-02-19 13 views
16

¿Cómo obtener 'System.Type' del módulo?Cómo obtener el tipo de módulo en F #

Por ejemplo módulo:

module Foo = 
    let bar = 1 

Y esto no funciona:

printfn "%s" typeof<Foo>.Name 

error es:

The type 'Foo' is not defined 
+1

Siendo curioso aquí. ¿Por qué tendrías que hacer esto? Usted sabe el nombre del módulo, Foo, y no creo que F # tenga la capacidad de pasar módulos como valor. Gracias. – nlucaroni

+0

La necesidad es simple, necesito algo de automatización. Puedo hacer esto con reflexión. PowerPack.Metadata permite iterar a través de módulos, pero puede haber algo más fácil. –

+0

Necesito hacer esto también para una API fuertemente tipada a una biblioteca que estoy escribiendo. – justin

Respuesta

7

Sin duda, sería bueno tener un operador moduleof .. . Como no hay ninguno, la forma más fácil de hacer lo que desea es, probablemente, utilizar la biblioteca de metadatos. en el 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 

Desafortunadamente, esto no funcionará con conjuntos dinámicos (tales como los generados a través de F # interactiva). Puede hacer algo similar utilizando las llamadas vainilla System.Reflection, pero eso depende más de tener una buena comprensión del formulario compilado que toma su módulo.

+0

El principal problema es que 'FSharpAssembly.FromAssembly asm' carga todos los tipos. También reduce la seguridad del tipo. –

+0

@Mike - No estoy seguro de lo que quiere decir con "reducir seguridad tipo" ... No hay forma de usar un módulo como un parámetro de tipo genérico, por lo que tendrá que usar una cadena. Esto es desafortunado, pero inevitable. – kvb

+3

¿Aún necesita un paquete de energía o hay una forma mejor 5 años después? – Maslow

-1

nombre del módulo no es un tipo.

List en List.map y let (a:List<int>) = [1;2;3] son diferentes.

El primer List es un nombre de módulo, el segundo es un tipo.

+5

Me preocupa 'FSharpType.IsModule (System.Type)', por lo que el tipo de módulo IS, al menos en términos CLR. –

+1

El nombre de la clase estática (tipo) a la que está compilado el módulo 'List' es probablemente' ListModule'. –

26

Se podría añadir un tipo de marcador al módulo y luego descubrir el tipo del módulo de eso:

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

También se puede hacer usando Quotations. En primer lugar, definir esta función auxiliar en alguna parte:

open Microsoft.FSharp.Quotations.Patterns 

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

A continuación, se puede definir un módulo y obtener su tipo así:

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

Espero que esto ayude.

+0

Esto no funciona en interactivo, ¿verdad? – BitTickler

+0

Lo hago por mí, aunque modifiqué la segunda parte para: 'module SomeName = let rec moduleType = getModuleType <@ moduleType @> ;;', then 'SomeName.moduleType ;;' debería generar la información del tipo. –

Cuestiones relacionadas