2009-03-12 8 views
2

J'ai joué avec F # et Reflection, en essayant de créer dynamiquement un objet de type Record à partir de F #, j'ai fonctionné la plupart du temps (comme vous pouvez le voir ci-dessous) mais une chose - le disque que je crée à travers la réflexion a le type "obj" à la place de celui qu'il devrait ("Person") et je n'arrive pas à le mettre en relief de quelque façon que ce soit.Upcasting F # enregistrement créé par la réflexion

#light 

type Person = { 
    Name:string; 
    Age:int; 
} 

let example = {Name = "Fredrik"; Age = 23;} 
// example has type Person = {Name = "Fredrik"; Age = 23;} 

let creator = Reflection.FSharpValue.PrecomputeRecordConstructor(example.GetType(), 
       System.Reflection.BindingFlags.Public) 

let reflected = creator [| ("thr" :> obj); (23 :> obj) |] 
// here reflected will have the type obj = {Name = "thr"; Age = 23;} 

// Function that changes the name of a Person record 
let changeName (x:Person) (name:string) = 
    { x with Name = name } 

// Works with "example" which is has type "Person" 
changeName example "Johan" 

// But not with "reflected" since it has type "obj" 
changeName reflected "Jack" // Error "This expression has type obj but is here used with type Person. " 

// But casting reflected to Person doesn't work either 
(reflected :> Person) // Type constraint mismatch. The type obj is not compatible with 
         // type Person. The type 'obj' is not compatible with the type 'Person'. 
         // C:\Users\thr\Documents\Visual Studio 2008\Projects\ 
         // Reflection\Reflection\Script.fsx 34 2 Reflection 

Répondre

2

Essayez d'utiliser l'autre opérateur coulé (comme vous coulée dans l'autre sens cette fois-ci)

Alors ChangeName (reflété :> personne) « Jack »

+0

Quelle est la différence entre l'opérateur:> et:?>? –

+0

La meilleure explication est probablement ici: http://stuff.mit.edu/afs/athena/software/fsharp_v1.1.12/FSharp-1.1.12.3/manual/import-interop.html#Upcasts Mais les bases sont que si vous allez d'une classe à son parent (c'est-à-dire quelque chose à obj), vous utilisez:>. Mais si vous allez dans l'autre sens, vous utilisez:?> ... – Massif

+2

":>" est un upcast, la conversion d'un objet en un type parent - c'est toujours sûr, et les erreurs de upcasting peuvent être interceptées par le compilateur. ":?>" est un downcast, convertit un objet en un type descendant - les downcasts ne sont jamais sûrs puisque les erreurs downcast entraînent toujours des exceptions d'exécution. – Juliet