编写一个类型提供程序并且我遇到了一个问题,我无法完全解决使用ProvideTypes的泛型参数添加现有接口的问题。如果有人知道如何将现有接口与通用参数一起添加到生成的类型中?
我想要的是生成类似于以下类型的类型,Bar和Foo都是生成类型。显然,以下是一个人为的例子。
type Bar() =
member val List: IEnumerable<Foo> with get, set
不幸的是,我在尝试使用实现接口typeof<IEnumerable<Foo>>
的ProvideType时遇到错误。我怀疑这是因为生成的类型被用作通用参数。
异常消息类似于:
不应在提供的情况下调用项目'Foo'上的操作'Module' 类型,成员或参数
编辑:我添加了简单的代码来重现错误(在DefineStaticParameters中调用):
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 ]
堆栈跟踪看起来像:
at Microsoft.FSharp.Core.Operators.Raise [T](Exception exn)at at ProviderImplementation.ProvidedTypes.Misc.notRequired并[a](字符串 opname,String item)ProvideTypes.fs:第58行\ at ProviderImplementation.ProvidedTypes.ProvidedTypeDefinition.get_Module() 在ProvideTypes.fs中:第1683行 System.Reflection.Emit.AssemblyBuilder.CheckContext(Type [] types)at System.Reflection.Emit.ModuleBuilder.GetTypeTokenWorkerNoLock(类型 type,Boolean getGenericDefinition)at System.Reflection.Emit.ModuleBuilder.GetTypeTokenInternal(Type type, 布尔getGenericDefinition)at System.Reflection.Emit.SignatureHelper.AddOneArgTypeHelperWorker(类型 clsArgument,Boolean lastWasGenericInst)at System.Reflection.Emit.SignatureHelper.AddOneArgTypeHelperWorker(类型 clsArgument,Boolean lastWasGenericInst)at System.Reflection.Emit.SignatureHelper.GetType SigToken(Module mod, 输入类型) System.Reflection.Emit.ModuleBuilder.GetTypeTokenWorkerNoLock(类型 type,Boolean getGenericDefinition)at System.Reflection.Emit.ModuleBuilder.GetTypeTokenInternal(Type type, 布尔getGenericDefinition)at System.Reflection.Emit.TypeBuilder.AddInterfaceImplementation(类型 interfaceType)
答案 0 :(得分:0)
经过进一步调查后,似乎类型提供程序初学者包中的Generated Types API不支持此功能。我提出了一个问题来解决这个问题。我怀疑添加到TypeBuilder的接口类型需要从ProvideTypeDefinition转换为实际的Reflection.Emit TypeBuilders,然后再作为接口添加到其他生成的类型,包括接口类型的所有泛型类型参数。
即IEnumerable&lt; GeneratedType&gt; - 我们需要首先转换泛型类型参数GeneratedType,然后创建一个引用转换类型的新类型实例(IEnumerable&lt; GeneratedType&gt;),然后将其添加为接口实现。将接口添加到类型的代码位于ProvideTypes.fs文件的AssemblyGenerator中。