2016-05-05 25 views
1

在編寫類型提供程序時遇到了問題,我遇到了一個問題,我無法完全瞭解如何使用屬性類型的通用參數添加現有接口。如果有人知道如何將通用參數的現有接口添加到生成的類型中?向生成的類型添加接口

我想要的是生成類似於下面的類型,Bar和Foo都是生成類型。顯然,以下是一個人爲的例子。

type Bar() = 
    member val List: IEnumerable<Foo> with get, set 

不幸的是試圖使用實現接口typeof<IEnumerable<Foo>>一個ProvidedType時,我得到一個錯誤。我懷疑這是因爲生成的類型被用作通用參數。

異常消息是這樣的:

上項「富」的操作「模塊」不應該提供 類型,構件或參數

EDIT被稱爲:我添加簡單的代碼來重現錯誤(稱爲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 ] 

堆棧跟蹤的樣子:

在Microsoft.FSharp.Core.Operators.Raise [T](例外EXN)在 ProviderImplementation.ProvidedTypes.Misc.notRequired並[a](字符串 opname,字符串項目)ProvidedTypes.fs:線58 \在 ProviderImplementation.ProvidedTypes.ProvidedTypeDefinition.get_Module()在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(模塊MOD, 型型)在 System.Reflection.Emit.ModuleBuilder.GetTypeTokenWorkerNoLock(類型 類型,布爾getGenericDefinition)在 System.Reflection.Emit.ModuleBuilder.GetTypeTokenInternal(類型類型, 布爾getGenericDefinition)在 系統.Reflection.Emit.TypeBuilder.AddInterfaceImplementation(Type interfaceType)

+0

你可能會看到使用'ProvidedTypeBuilder.MakeGenericType'是否有幫助。 – kvb

+0

它讓我更進一步,但現在我遇到了IEnumerable的提供的符號類型的問題 - 它不是在抱怨GetAttributeFlagsImpl不應該被調用。我不確定是否應該嘗試在ProvidedSymbolType上實現該方法,或者如果我在做其他問題。 – akara

+0

創建一個實現GetAttributeFlagsImpl的自定義SymbolType,從傳入的通用IEnumerable <>類型中獲取其類型屬性以構建它(更改ProvidedTypeBuilder.MakeGenericType捕獲此)讓我回到問題中的原始錯誤。不知道我應該如何填充Module屬性。 – akara

回答

0

經過進一步調查,似乎類型提供程序入門包中的生成類型API不支持此功能。我提出了一個問題來解決這個問題。我懷疑添加到TypeBuilder的接口類型需要從ProvidedTypeDefinition轉換爲實際的Reflection.Emit TypeBuilder,然後才能作爲接口添加到其他生成的類型,包括接口類型的所有泛型類型參數。

i。e for IEnumerable < GeneratedType> - 我們需要首先轉換泛型類型參數GeneratedType,然後創建一個引用轉換後類型的新類型實例(IEnumerable < GeneratedType>),然後將其添加爲接口實現。將接口添加到類型的代碼位於SuggestedTypes.fs文件的AssemblyGenerator中。