beiseite Putting den Nutzen des Endergebnisses, ein Ausschnitt unten erreicht genau das, was Sie im Geiste der my other related answer gestellt:
#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
Eine Skizze Umsetzung RecordTypeMaker
nimmt eine willkürliche Record type
Definition mit type name
und Array von field names
begleitet von field type names
. Dann wird hinter dem Vorhang ein Stück F # -Code zusammengesetzt, das den angeforderten Datensatztyp definiert, kompiliert diesen Code über CodeDom provider
, lädt Container-Assembly und bietet Zugriff auf diesen neu erstellten synthetischen Datensatztyp über Reflection. Ein Test-Schnipsel
let myType = RecordTypeMaker("Test", [|("Field1", "string"); ("Field2", "int")|]).RecordType
printfn "IsRecordType=%b" (FSharpType.IsRecord(myType))
printfn "Record fields: %A" (FSharpType.GetRecordFields(myType))
demonstriert für einen rein synthetischen Typ myType
der Proof of Concept:
IsRecordType=true
Record fields: [|System.String Field1; Int32 Field2|]
Ich verstehe nicht, wie würden Sie einen Datensatztyp verwenden, die sonst dynamisch erstellt wurde? Im Gegensatz zu: 'type MyRecord = {field1: string, field2: string}' – yamen
@yamen würde ich es genauso verwenden wie jeden anderen Typ. – nicolas
Was ich meine ist - wenn Sie eine dynamische Liste von Eigenschaften bereitstellen, verwenden Sie sie dann dynamisch oder statisch? Wenn es statisch ist, warum sollte es nicht zuerst statisch definiert werden? – yamen