F# 向生成的类型添加接口
在尝试编写类型提供程序时,我遇到了一个问题,特别是在添加具有提供类型的泛型参数的现有接口方面,我不能完全克服这个问题。如果有人知道如何将具有泛型参数的现有接口添加到生成的类型中 我想要的是生成一个类似于下面的类型,其中Bar和Foo都是生成的类型。显然,下面的例子是人为的F# 向生成的类型添加接口,f#,type-providers,F#,Type Providers,在尝试编写类型提供程序时,我遇到了一个问题,特别是在添加具有提供类型的泛型参数的现有接口方面,我不能完全克服这个问题。如果有人知道如何将具有泛型参数的现有接口添加到生成的类型中 我想要的是生成一个类似于下面的类型,其中Bar和Foo都是生成的类型。显然,下面的例子是人为的 type Bar() = member val List: IEnumerable<Foo> with get, set type Bar()= 成员值列表:IEnumerable with get,se
type Bar() =
member val List: IEnumerable<Foo> with get, set
type Bar()=
成员值列表:IEnumerable with get,set
不幸的是,我在尝试使用实现接口typeof
的ProvidedType时出错。我怀疑这是因为生成的类型被用作泛型参数
异常消息类似于:
不应在提供的上调用项“Foo”上的操作“Module”
类型、成员或参数
编辑:我添加了简单的代码来重现错误(在DefineStaticParameters中调用):
let buildType()=
让providedType1=ProvidedTypeDefinition(“父类型”,某些类型的,iSeries=false)
让providedType2=ProvidedTypeDefinition(“数据类型”,某些类型的,iSeries=false)
让symbolType=ProvidedTypeBuilder.MakeGenericType(typedefof,[providedType2])
设providedField=providedField(“propertyField”,symbolType)
providedType1.AddMember(providedField)
让providedProperty=providedProperty(“TestProperty”,symbolType)
ProviderProperty.GetterCode Expr.FieldGet(参数[0],ProviderField)
providedType1.AddMember providedProperty
设pconstructor=ProvidedConstructor([ProvidedParameter(“dataList”,symbolType)])
pconstructor.InvokeCode
提供的类型1.AddMember pconstructor
让nestedProperty=ProvidedProperty(“数据”,typeof)
nestedProperty.GetterCode
providedType2.AddMember nestedProperty
让interfaceType=ProvidedTypeBuilder.MakeGenericType(typedefof,[providedType2])
providedType2.AddInterfaceImplementation接口类型
让equalsParameter=ProvidedParameter(“其他”,providedType2)
让providedMethodEquals=ProvidedMethod(“Equals”,[equalsParameter],typeof)
providedMethodEquals.InvokeCode
设propertyGet x=Expr.propertyGet(x,nestedProperty)
设currentEq=propertyGet参数。[0]
让otherEq=propertyGet参数[1]
//将它们添加到生成的类型中,命名空间在此方法之外
[提供的类型1;提供的类型2]
堆栈跟踪看起来像:
在Microsoft.FSharp.Core.Operators.Raise[T](异常exn)的
ProviderImplementation.ProvidedTypes.Misc.notRequired[a](字符串
opname,字符串项)ProvidedTypes.fs:第58行\at
ProviderImplementation.ProvidedTypes.ProvidedTypeDefinition.get_模块()
在ProvidedTypes.fs中:第1683行
位于的System.Reflection.Emit.AssemblyBuilder.CheckContext(类型[]类型)
System.Reflection.Emit.ModuleBuilder.GetTypeTokenWorkerNoLock(类型
类型,布尔getGenericDefinition)位于
System.Reflection.Emit.ModuleBuilder.GetTypeTokenInternal(类型,
布尔getGenericDefinition)位于
System.Reflection.Emit.SignatureHelper.AddOneArgTypeHelperWorker(类型
clsArgument,布尔值lastWasGenericInst)位于
System.Reflection.Emit.SignatureHelper.AddOneArgTypeHelperWorker(类型
clsArgument,布尔值lastWasGenericInst)位于
System.Reflection.Emit.SignatureHelper.GetType SigToken(模块修改,
类型)在
System.Reflection.Emit.ModuleBuilder.GetTypeTokenWorkerNoLock(类型
类型,布尔getGenericDefinition)位于
System.Reflection.Emit.ModuleBuilder.GetTypeTokenInternal(类型,
布尔getGenericDefinition)位于
System.Reflection.Emit.TypeBuilder.AddInterfaceImplementation(类型
接口类型)
经过进一步调查,似乎类型提供程序启动包中生成的类型API目前还不支持此功能。我提出了一个关于这个案子的问题。我怀疑添加到TypeBuilder的接口类型需要从提供的TypeDefinition转换为实际反射。在作为接口添加到其他生成的类型(包括接口类型的所有泛型类型参数)之前,请发出TypeBuilder
i、 e对于IEnumerable
i、 e对于IEnumerable
ProvidedTypeBuilder.MakeGenericType
是否有帮助。这让我更进一步,但现在我对IEnumerable的ProvidedSymbolType有一个问题-它并不抱怨不应该调用GetAttributeFlagsImpl。我不确定是否应尝试在提供的SymbolType上实现该方法,或者是否执行了其他错误操作。创建一个实现GetAttributeFlagsImpl的自定义SymbolType从传入的泛型IEnumerable类型获取其类型属性以生成它(修改后的ProvidedTypeBuilder.MakeGenericType将捕获此信息)把我带回到办公室
let buildType() =
let providedType1 = ProvidedTypeDefinition("ParentType", Some typeof<obj>, IsErased = false)
let providedType2 = ProvidedTypeDefinition("DataType", Some typeof<obj>, IsErased = false)
let symbolType = ProvidedTypeBuilder.MakeGenericType(typedefof<IEnumerable<_>>, [providedType2])
let providedField = ProvidedField("propertyField", symbolType)
providedType1.AddMember(providedField)
let providedProperty = ProvidedProperty("TestProperty", symbolType)
providedProperty.GetterCode <- fun args -> Expr.FieldGet(args.[0], providedField)
providedType1.AddMember providedProperty
let pconstructor = ProvidedConstructor([ProvidedParameter("dataList", symbolType)])
pconstructor.InvokeCode <- fun args -> <@@ () @@>
providedType1.AddMember pconstructor
let nestedProperty = ProvidedProperty("Data", typeof<string>)
nestedProperty.GetterCode <- fun _ -> <@@ "TEST SUCCESS" @@>
providedType2.AddMember nestedProperty
let interfaceType = ProvidedTypeBuilder.MakeGenericType(typedefof<IEquatable<_>>, [providedType2])
providedType2.AddInterfaceImplementation interfaceType
let equalsParameter = ProvidedParameter("other", providedType2)
let providedMethodEquals = ProvidedMethod("Equals", [ equalsParameter ], typeof<bool>)
providedMethodEquals.InvokeCode <- fun args ->
let propertyGet x = Expr.PropertyGet(x, nestedProperty)
let currentEq = propertyGet args.[0]
let otherEq = propertyGet args.[1]
<@@ %%currentEq = %%otherEq @@>
// Add these to the generated type with a namespace outside this method
[ providedType1; providedType2 ]