F# 类型提供程序 - 嵌套属性实例化
F# Type Providers - nested properties instantiation
我正在尝试构建我的第一个类似玩具的 Type Provider。我想要实现的是动态生成 动态生成类型 的属性。
collection
|> getItems
|> Seq.map(fun mapItem ->
let nestedType = ProvidedTypeDefinition(assembly, ns, "MyNestedType", None)
let ctor = ProvidedConstructor(List.Empty)
nestedType.AddMember ctor
mapItem.Value
|> Seq.map(fun pair ->
ProvidedProperty(fst(pair), typeof<string>,
GetterCode = fun [_] -> <@@ snd(pair) @@>))
|> Seq.toList
|> nestedType.AddMembers
ProvidedProperty(mapItem.Key, nestedType,
GetterCode = fun [map] ->
// ?? Runtime Exception
let inst = nestedType.GetConstructors().[0].Invoke([||])
<@@ inst @@>
))
|> Seq.toList
|> ty.AddMembers
ty
我应该如何实例化动态生成的类型?
我假设这是一个擦除类型的提供程序(这些很简单,所以它们是入门的更好选择)。如果不是这样,请无视我的回答。
在 GetterCode
中,您不需要创建 嵌套提供类型 的实例。您只需要创建一个类型的实例,它被擦除为。
在您的情况下,nestedType
被擦除为 None
,因此构造函数只需要创建一个 System.Object
值,因此您应该能够使用:
ProvidedProperty(mapItem.Key, nestedType,
GetterCode = fun [self] -> <@@ obj() @@>)
实际上,您可能希望擦除为某种类型,以便保留嵌套类型应该访问的一些数据。如果嵌套类型被擦除为 MyRuntimeType
,那么您可以这样写:
let parameter = mapItem.WhateverYouWantHere
ProvidedProperty(mapItem.Key, nestedType,
GetterCode = fun [self] -> <@@ MyRuntimeType(parameter) @@>)
请注意,我使用 let
来捕获原始 parameter
类型的值,以便编译器可以序列化引用(您不能在引用中捕获复杂的对象类型)。
您在这里尝试做的是在构建提供程序 时实例化您的类型,然后将该新实例包含在属性 的主体中。应该非常清楚的是,您不能在完成提供类型之前实例化提供的类型。
您真正想要做的是采用您提供的构造函数并构建调用它的引用。你不能让编译器为你构建引用,因为为了让编译器编译引用的主体,它需要 "see" 全部 types/methods/functions 在里面,而你的类型还没有准备好.但是您可以使用 Quotations.Expr
下的各种构造函数手动创建报价单。在这种情况下,NewObject
是合适的:
GetterCode = fun [map] -> Expr.NewObject (ctor, [])
我正在尝试构建我的第一个类似玩具的 Type Provider。我想要实现的是动态生成 动态生成类型 的属性。
collection
|> getItems
|> Seq.map(fun mapItem ->
let nestedType = ProvidedTypeDefinition(assembly, ns, "MyNestedType", None)
let ctor = ProvidedConstructor(List.Empty)
nestedType.AddMember ctor
mapItem.Value
|> Seq.map(fun pair ->
ProvidedProperty(fst(pair), typeof<string>,
GetterCode = fun [_] -> <@@ snd(pair) @@>))
|> Seq.toList
|> nestedType.AddMembers
ProvidedProperty(mapItem.Key, nestedType,
GetterCode = fun [map] ->
// ?? Runtime Exception
let inst = nestedType.GetConstructors().[0].Invoke([||])
<@@ inst @@>
))
|> Seq.toList
|> ty.AddMembers
ty
我应该如何实例化动态生成的类型?
我假设这是一个擦除类型的提供程序(这些很简单,所以它们是入门的更好选择)。如果不是这样,请无视我的回答。
在 GetterCode
中,您不需要创建 嵌套提供类型 的实例。您只需要创建一个类型的实例,它被擦除为。
在您的情况下,nestedType
被擦除为 None
,因此构造函数只需要创建一个 System.Object
值,因此您应该能够使用:
ProvidedProperty(mapItem.Key, nestedType,
GetterCode = fun [self] -> <@@ obj() @@>)
实际上,您可能希望擦除为某种类型,以便保留嵌套类型应该访问的一些数据。如果嵌套类型被擦除为 MyRuntimeType
,那么您可以这样写:
let parameter = mapItem.WhateverYouWantHere
ProvidedProperty(mapItem.Key, nestedType,
GetterCode = fun [self] -> <@@ MyRuntimeType(parameter) @@>)
请注意,我使用 let
来捕获原始 parameter
类型的值,以便编译器可以序列化引用(您不能在引用中捕获复杂的对象类型)。
您在这里尝试做的是在构建提供程序 时实例化您的类型,然后将该新实例包含在属性 的主体中。应该非常清楚的是,您不能在完成提供类型之前实例化提供的类型。
您真正想要做的是采用您提供的构造函数并构建调用它的引用。你不能让编译器为你构建引用,因为为了让编译器编译引用的主体,它需要 "see" 全部 types/methods/functions 在里面,而你的类型还没有准备好.但是您可以使用 Quotations.Expr
下的各种构造函数手动创建报价单。在这种情况下,NewObject
是合适的:
GetterCode = fun [map] -> Expr.NewObject (ctor, [])