When do I need to call the "ConvertToGenerated" member to generate types using a type provider

It’s hard for me to decipher the section “Providing Generated Types”. A model guide for the provider . The tutorial contains the following specification.

"You must also call ConvertToGenerated on the root type whose nested types form a private set of generated types. This call returns the specified type definition and its nested type definitions to the assembly and sets the Assembly property for all provided definition types to return this assembly. The assembly is emitted only when access to the Assembly property in the root type first appears. The host compiler F # accesses this property when it processes the declaration of the generative type for that type. "

I do not know where to place the ConvertToGenerated call, and I am not sure about the requirements of the assembly file name parameter. Can someone give an example? Thanks.

+6
source share
1 answer

After some help from the F # team, I solved my problem. This is what I did.

namespace Types open System open System.Data open System.IO open System.Linq open System.Data.Linq open Microsoft.FSharp.Data.TypeProviders open Microsoft.FSharp.Linq open Microsoft.FSharp.TypeProvider.Emit open Microsoft.FSharp.Core.CompilerServices type DatabaseSchema = SqlDataConnection<"Data Source=(local);Initial Catalog=Test;Integrated Security=SSPI;"> [<TypeProvider>] type public MeasureTypeProvider(cfg:TypeProviderConfig) as this = inherit TypeProviderForNamespaces() let assembly = System.Reflection.Assembly.GetExecutingAssembly() let typesNamespace = "Types.Domain" let providedTypeBuilder = ProvidedTypeBuilder.Default let db = DatabaseSchema.GetDataContext() let types = query { for m in db.Table do select m } |> Seq.map(fun dataEntity -> let className:string = dataEntity.Identifier let providedTypeDefinition = ProvidedTypeDefinition(className = className, baseType = Some typeof<obj>, IsErased=false) providedTypeDefinition.AddMember( ProvidedConstructor([], InvokeCode = fun [] -> <@@ obj() @@>)) providedTypeDefinition ) |> Seq.toList let rootType = let providedTypeDefinition = ProvidedTypeDefinition(assembly, typeNamespace, "DomainTypes", Some typeof<obj>, IsErased=false) providedTypeDefinition.AddMembersDelayed(fun () -> types) this.AddNamespace(typesNamespace, [providedTypeDefinition]) providedTypeDefinition let path = Path.GetDirectoryName(assembly.Location) + @"\GeneratedTypes.dll" do rootMeasureType.ConvertToGenerated(path) [<assembly:TypeProviderAssembly>] do() 

The TypeProvider.Emit structure automatically clears the generated assembly. Comment on the following expression if you want it to stick.

 File.Delete assemblyFileName 

Another problem I found is that although I was able to provide types that are inferred from value types (e.g. decimal) when IsErased = true, I could not provide these derived types when IsErased = false. This is because value types are sealed, so it is not possible to create a "real" type derived from a value type.

+4
source

Source: https://habr.com/ru/post/913457/


All Articles