6

我很难解读Type Provider Tutorial的“提供生成的类型”部分。本教程提供了以下规范。

“您还必须在根提供的类型上调用 ConvertToGenerated,其嵌套类型形成一组封闭的生成类型。此调用将给定的提供的类型定义及其嵌套类型定义发送到程序集中,并调整所有提供的类型定义的 Assembly 属性以返回“

我不知道在哪里放置 ConvertToGenerated 调用,我不确定程序集文件名参数的要求。有人可以提供一个例子吗?谢谢。

4

1 回答 1

4

在 F# 团队的帮助下,我解决了我的问题。这就是我所做的。

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()

TypeProvider.Emit 框架会自动清理生成的程序集。如果您希望它保留下来,请注释掉以下语句。

File.Delete assemblyFileName

我发现的另一个问题是,虽然当 IsErased=true 时我能够提供从值类型(如十进制)派生的类型,但当 IsErased=false 时我无法提供这些派生类型。这是因为值类型是密封的,因此不可能生成从值类型派生的“真实”类型。

于 2012-04-21T01:15:08.687 回答