F#类型提供程序生成类型
我正在尝试创建一个类型提供程序,它生成类型并且不删除它们。我使用GeneratedTypeProvider示例并制作了自己的版本 我试图实现的是,某个类型是generate(例如Fact),它有一个用于该类型及其属性(例如Id、时间戳、名称)的构造函数。我使用元素类型作为基类型。构造应该导致一个不可变的事实对象 如果我在一个擦除的变体中运行它,一切都很好,但是我没有得到事实类型。当我制作非擦除版本时(设置typesTy.IsErased Seq.mapi(fun I value->(I,value))) 成员this.GetValue propertyIndex:obj= 将propertyMap.TryFind propertyIndex与匹配 |一些(值)->值 |无->框“未找到属性” 让elementType的私有类型= 将elementType与 |“字符串”->typeof |“Guid”->typeof |“日期时间”->typeof |_uu->typeof 让内部MakeType使用此程序集名称空间名称组entityName= 让entityType= 提供的类型定义(此程序集、命名空间名称、, entityName, baseType=某种类型的 entityType.AddXmlDocDelayed(fun()->sprintf“This%s”entityName) 让属性=[(“Id”、“Guid”);(“时间戳”、“日期时间”);(“名称”、“字符串”)] 让我们来看看这些属性= 性质 |>List.iteri(乐趣索引(propertyName,propertyType)-> 设instanceProp= ProviderProperty(propertyName=propertyName, propertyType=propertyType的类型, GetterCode=(有趣的参数->) instanceProp.AddXmlDocDelayed(fun()->sprintf“%s”属性名称) entityType.AddMember instanceProp) 让类型构造函数= 提供的构造函数( 参数= (属性 |>List.mapi(有趣的索引(名称,类型)->提供的参数(parameterName=name,parameterType=typeOf-typ)), 调用代码= (有趣的args-> 让boxedArgs= args |>List.map(有趣的arg-> 将arg与 |QUOTES.Patterns.Var-> 如果变量类型=类型,则 否则,如果变量类型=类型,则 否则,如果变量类型=类型,则 否则,如果变量类型=类型,则 其他的 设argsVals= args |>List.map(有趣的arg-> 将arg与 |QUOTES.Patterns.Var->Var.Type.ToString() |——>“未知”) |>List.reduce(全部参数->全部+,“+arg) failwith(“啊哈:+argsVals”) |->failwith(“未知表达式作为参数”)) obj@@>)) AddXmlDocDelayed(fun()->“这是构造函数”) entityType.AddMember类型构造函数 实体类型 [] 键入publicDatalayerProvider(cfg:TypeProviderConfig),如下所示= 继承TypeProviderForNamespaces() 让thisAssembly=Assembly.getExecutionGassembly() 让rootNamespace=“类型” 让providedAssembly=newprovidedAssembly(System.IO.Path.ChangeExtension(System.IO.Path.GetTempFileName(),“.dll”)) 让typesTy=makeTypeWith thissassembly rootNamespace“Some”Fact 做 类型化 让name=System.Reflection.AssemblyName(args.name) 让现有程序集= System.AppDomain.CurrentDomain.GetAssemblys() |>Seq.tryFind(fun a->System.Reflection.AssemblyName.ReferenceMatchesDefinition(name,a.GetName())) 将现有程序集与匹配 |一些a->a |无->空) 执行此操作。AddNamespace(rootNamespace,[typesTy]) [] do()F#类型提供程序生成类型,f#,type-providers,F#,Type Providers,我正在尝试创建一个类型提供程序,它生成类型并且不删除它们。我使用GeneratedTypeProvider示例并制作了自己的版本 我试图实现的是,某个类型是generate(例如Fact),它有一个用于该类型及其属性(例如Id、时间戳、名称)的构造函数。我使用元素类型作为基类型。构造应该导致一个不可变的事实对象 如果我在一个擦除的变体中运行它,一切都很好,但是我没有得到事实类型。当我制作非擦除版本时(设置typesTy.IsErased Seq.mapi(fun I value->(I,valu
您可能想看看非擦除的工作示例,根据
ProviderdTypes head.fs中的代码行判断,在该异常之前,它希望元素类型具有无参数构造函数:let cinfo=ptd.BaseType.GetConstructor(BindingFlags.Public | | | | | | BindingFlags.NonPublic | | | | BindingFlags.Instance,null,[| |],null)如果您描述您正试图使用此类型提供程序实现什么,这将非常有帮助。除了INotifyPropertyChange TP之外,我建议您仔细阅读,并详细描述它应该如何实现。
type Element(values: obj []) =
let propertyMap = new Map<int, obj>(values |> Seq.mapi (fun i value -> (i, value)))
member this.GetValue propertyIndex : obj =
match propertyMap.TryFind propertyIndex with
| Some(value) -> value
| None -> box "property not found"
let private typeOf elementType =
match elementType with
| "String" -> typeof<string>
| "Guid" -> typeof<System.Guid>
| "DateTime" -> typeof<System.DateTime>
| _ -> typeof<string>
let internal makeTypeWith thisAssembly namespaceName group entityName =
let entityType =
ProvidedTypeDefinition(thisAssembly, namespaceName,
entityName,
baseType = Some typeof<Element>)
entityType.AddXmlDocDelayed (fun () -> sprintf "This %s" entityName)
let properties = [("Id", "Guid"); ("Timestamp", "DateTime"); ("Name", "String")]
let fieldsOfProperties =
properties
|> List.iteri (fun index (propertyName, propertyType) ->
let instanceProp =
ProvidedProperty(propertyName = propertyName,
propertyType = typeOf propertyType,
GetterCode = (fun args -> <@@ unbox ((%%(args.[0]) : Element).GetValue index) @@>))
instanceProp.AddXmlDocDelayed(fun () -> sprintf "%s" propertyName)
entityType.AddMember instanceProp)
let typeConstructor =
ProvidedConstructor(
parameters =
(properties
|> List.mapi (fun index (name, typ) -> ProvidedParameter(parameterName = name, parameterType = typeOf typ))),
InvokeCode =
(fun args ->
let boxedArgs =
args |> List.map (fun arg ->
match arg with
| Quotations.Patterns.Var var ->
if var.Type = typeof<int> then
<@@ (box (%%arg: int)) @@>
else if var.Type = typeof<string> then
<@@ (box (%%arg: string)) @@>
else if var.Type = typeof<System.Guid> then
<@@ (box (%%arg: System.Guid)) @@>
else if var.Type = typeof<System.DateTime> then
<@@ (box (%%arg: System.DateTime)) @@>
else
let argsVals =
args |> List.map (fun arg ->
match arg with
| Quotations.Patterns.Var var -> var.Type.ToString()
| _ -> "unknown")
|> List.reduce (fun all arg -> all + ", " + arg)
failwith ("Aha: " + argsVals)
| _ -> failwith ("Unknown Expr as parameter"))
<@@ Element(%%(Expr.NewArray(typeof<obj>, boxedArgs))) :> obj @@>))
typeConstructor.AddXmlDocDelayed(fun () -> "This is the constructor")
entityType.AddMember typeConstructor
entityType
[<TypeProvider>]
type public DataLayerProvider(cfg:TypeProviderConfig) as this =
inherit TypeProviderForNamespaces()
let thisAssembly = Assembly.GetExecutingAssembly()
let rootNamespace = "Types"
let providedAssembly = new ProvidedAssembly(System.IO.Path.ChangeExtension(System.IO.Path.GetTempFileName(), ".dll"))
let typesTy = makeTypeWith thisAssembly rootNamespace "Some" "Fact"
do
typesTy.IsErased <- false
providedAssembly.AddTypes([typesTy])
do System.AppDomain.CurrentDomain.add_AssemblyResolve(fun _ args ->
let name = System.Reflection.AssemblyName(args.Name)
let existingAssembly =
System.AppDomain.CurrentDomain.GetAssemblies()
|> Seq.tryFind(fun a -> System.Reflection.AssemblyName.ReferenceMatchesDefinition(name, a.GetName()))
match existingAssembly with
| Some a -> a
| None -> null)
do this.AddNamespace(rootNamespace, [typesTy])
[<TypeProviderAssembly>]
do ()