2009-03-12 2 views
2

F #과 그 리플렉션에 대해 망쳤습니다. F #에서 레코드 유형 오브젝트를 동적으로 만들려고 노력했지만 대부분은 작동했습니다 (아래에서 볼 수 있듯이) 리플렉션을 통해 만드는 레코드에는 "obj"유형 (예 : Person)이 있어야하며 어떤 방식 으로든 업 스케일 할 수없는 것처럼 보입니다.리플렉션을 통해 생성 된 Upcasting F # 레코드

#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 

답변

2

그래서로 changeName을 (당신은 다른 방법이 시간을 캐스팅하고 같은) 다른 캐스트 연산자를 사용해보십시오 (반영 :?> 사람) "잭"

+0

사이의 차이 무엇입니까 :> 및 :?> 연산자? –

+0

아마도 가장 좋은 설명은 여기에 있습니다 : http://stuff.mit.edu/afs/athena/software/fsharp_v1.1.12/FSharp-1.1.12.3/manual/import-interop.html#Upcasts 기본 사항은 다음과 같습니다. 클래스에서 상위 클래스로 이동하는 경우 (예 : obj), 다음을 사용합니다.> 하지만 다른 방법을 사용하면?> ... – Massif

+2

":>"은 업스트림이며 개체를 부모 형식으로 변환합니다. 항상 안전하며 업 캐스팅 오류는 컴파일러에서 발견 할 수 있습니다. ":?>"는 다운 캐스트 (downcast)이며 객체를 자손 유형으로 변환합니다. 다운 캐스팅 오류는 항상 런타임 예외가 발생하므로 안전하지 않습니다. – Juliet

관련 문제