2012-04-14 2 views
1

제공되는 필드를 기반으로 간단한 레코드 유형을 만들고 싶습니다. 이다F #에서 레코드 유형 생성

:

let rectype = MakeRecordType(['fieldname1'; 'fieldname2']) 

가 공급자를 입력로 직접 이동은 간단한 작업에 대한 무거운 gunpower 것 같습니다.

다른 방법이 있습니까? 갱신

내가 Creating F# record through reflection

+2

: 테스트 조각

let myType = RecordTypeMaker("Test", [|("Field1", "string"); ("Field2", "int")|]).RecordType printfn "IsRecordType=%b" (FSharpType.IsRecord(myType)) printfn "Record fields: %A" (FSharpType.GetRecordFields(myType)) 

는 순수하게 합성 형 myType 개념의 증거를 보여? 'type MyRecord = {field1 : string, field2 : string}' – yamen

+0

@yamen 다른 형식과 거의 같은 방식으로 사용합니다. – nicolas

+0

무슨 뜻입니까? 동적 속성 목록을 제공하는 경우 동적으로 또는 정적으로 사용합니까? 정적이라면 먼저 정적으로 정의하지 않겠습니까? – yamen

답변

5

은 최종 결과의 유용성을 따로 두는 매우 유사 다음과 같은 질문을 발견, 아래의 코드 조각은 my other related answer의 정신을 요구 정확히 무엇을 달성 :

#if INTERACTIVE 
#r @"C:\Program Files (x86)\Microsoft F#\v4.0\FSharp.Compiler.dll" 
#r @"C:\Program Files (x86)\FSharpPowerPack-1.9.9.9\bin\FSharp.Compiler.CodeDom.dll" 
#endif 

open System 
open System.CodeDom.Compiler 
open Microsoft.FSharp.Compiler.CodeDom 
open Microsoft.FSharp.Reflection 

type RecordTypeMaker (typeName: string, records: (string*string) []) = 
    let _typeDllName = "Synth"+typeName+".dll" 
    let _code = 
     let fsCode = new System.Text.StringBuilder() 
     fsCode.Append("module ").Append(typeName).Append(".Code\ntype ").Append(typeName).Append(" = {") |> ignore 
     for rec' in records do fsCode.Append(" ").Append(fst rec').Append(" : ").Append(snd rec').Append(";\n") |> ignore 
     fsCode.Append("}").ToString() 
    let _compiled = 
     use provider = new FSharpCodeProvider() 
     let options = CompilerParameters([||], _typeDllName) 
     let result = provider.CompileAssemblyFromSource(options, [|_code|]) 
     result.Errors.Count = 0 
    let mutable _type: Type = null 

    member __.RecordType 
     with get() = if _compiled && _type = null then 
         _type <- Reflection.Assembly.LoadFrom(_typeDllName).GetType(typeName+".Code+"+typeName) 
        _type 

RecordTypeMaker의 스케치 구현은 임의허용 배열은 type name이고 배열은 field names이고, 배열은 field type names입니다. 그런 다음 커튼 뒤에 요청 된 레코드 유형을 정의하는 F # 코드를 어셈블하고 CodeDom provider을 통해이 코드를 컴파일하고 컨테이너 어셈블리를로드하고 Reflection을 통해 새로 생성 된 합성 레코드 유형에 대한 액세스를 제공합니다. 당신이 그렇지 않으면 동적으로 생성 된 레코드 유형을 사용하는 방법을 이해하지 않습니다

IsRecordType=true 
Record fields: [|System.String Field1; Int32 Field2|] 
+0

매우 근사합니다. 나는 놀랐지 만, 나는 동적 linq 쿼리를 얻기 위해 csharp에서 2005 년에 똑같은 팬시 트릭을하고 있었다. 7 년 후, 우리는 같은 장소에 거의 같은 유형의 창조물을 만들었습니다. – nicolas

+1

@nicolas : F # 및 C#은 _ 정적으로 입력 된 언어 _입니다. 런타임 유형 생성은 이유가있는 경우 간단하거나 내장되지 않습니다. – ildjarn

+0

@ildjam 및 형식 공급자도 존재합니다. – nicolas