我希望基于提供的字段创建一个简单的记录类型。
也就是说:
也就是说:
let rectype = MakeRecordType(['fieldname1'; 'fieldname2'])
直接使用类型提供程序似乎对于这样一个简单的任务来说有些过于浪费。
还有其他方法吗?
更新
我发现了下面这个问题,它看起来非常相似 通过反射创建F#记录
let rectype = MakeRecordType(['fieldname1'; 'fieldname2'])
直接使用类型提供程序似乎对于这样一个简单的任务来说有些过于浪费。
还有其他方法吗?
更新
我发现了下面这个问题,它看起来非常相似 通过反射创建F#记录
暂且不论最终结果的有用性,在下面的代码片段中,如我的其他相关回答所述,完全实现了你的要求:
#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
的草图实现接受一个任意的记录类型
定义,其中包含类型名称
和一组字段名称
,并伴随着字段类型名称
。然后,在幕后它会组装一段F#代码来定义所请求的记录类型,通过CodeDom提供程序
编译这段代码,加载容器程序集,并通过反射提供对这个新创建的合成记录类型的访问。下面是一个测试片段:
let myType = RecordTypeMaker("Test", [|("Field1", "string"); ("Field2", "int")|]).RecordType
printfn "IsRecordType=%b" (FSharpType.IsRecord(myType))
printfn "Record fields: %A" (FSharpType.GetRecordFields(myType))
myType
的概念证明:IsRecordType=true
Record fields: [|System.String Field1; Int32 Field2|]
type MyRecord = { field1: string, field2: string}
- yamenDictionary<>
就可以完成。 - ildjarn