错误 FS3039: 不允许直接引用生成的类型'MyType'

15
以下类型提供程序旨在创建 GeneratedNamespace.MyType,它接受类型为 string 的静态参数并仅包含一个空构造函数。
namespace TypeProviderTest

open Microsoft.FSharp.Core.CompilerServices
open ProviderImplementation.ProvidedTypes
open System.Reflection
open System

[<TypeProvider>]
type MyTypeProvider(config:TypeProviderConfig) as this = 
    inherit TypeProviderForNamespaces()
    let namespaceName="GeneratedNamespace"
    let assembly = Assembly.LoadFrom(config.RuntimeAssembly)

    //Provides definition, based on type parameters
    let instantiationFunction typeName (typeParams:obj[]) =
        match typeParams with
                | [|:? string as param|] -> 
                    //Creates an empty non-erased type
                    let definition = ProvidedTypeDefinition(
                                        assembly,
                                        namespaceName,
                                        typeName,
                                        Some typedefof<Object>,
                                        IsErased = false
                                        )

                    //Creates an empty constructor
                    let emptyCtor = ProvidedConstructor (parameters = [])
                    //Provides a call to base constructor 
                    //(https://dev59.com/533aa4cB1Zd3GeqPiMwv)
                    //Doesn't seem to help
                    let objCtor = typedefof<Object>.GetType().GetConstructor([||])
                    emptyCtor.BaseConstructorCall <- (fun _ -> objCtor,[])
                    emptyCtor.AddXmlDoc("Empty constructor test")

                    definition.AddMember(emptyCtor)
                    definition
                | _ -> failwith "That was not supported"

    let  staticParams = [ProvidedStaticParameter("value",typedefof<string>)] 
    let t = ProvidedTypeDefinition(assembly,namespaceName,"MyType",Some typedefof<Object>)
    do t.DefineStaticParameters(staticParams,instantiationFunction)


    do this.AddNamespace(namespaceName,[t])
[<assembly:TypeProviderAssembly>]
do ()

当我尝试像这样使用它时:
open System
open GeneratedNamespace
type X = MyType<"Abacaba">
[<EntryPoint>]
let main argv = 
    printfn "%A %A" typedefof<X> (new X())
    Console.ReadLine() |> ignore
    0 

这行代码type X = MyType<"Abacaba">产生了错误

错误 FS3039: 不允许直接引用生成的类型'MyType'。

我添加了一个基础构造函数调用,但没有帮助

类型提供程序是有意生成的

我的类型提供程序有错误吗?

1个回答

6
我不确定如何完全使其工作,但我认为你收到错误的原因是参数化类型是擦除类型(而静态参数提供后返回的类型不是擦除类型)。
t 中添加 IsErased = false 可以消除错误。
let  staticParams = [ProvidedStaticParameter("value",typedefof<string>)] 
let t = 
  ProvidedTypeDefinition
    (assembly,namespaceName,"MyType",Some typedefof<Object>,IsErased = false)
do t.DefineStaticParameters(staticParams,instantiationFunction)

这样,代码可以编译,但是使用new X()创建实例时会出现以下错误:

error FS0192: internal error: null: GetTRefType

因此,我可能还缺少其他东西。也许这些能够指引您朝正确的方向前进!


文档中是否确认参数化类型应该被擦除? - user2136963
发现了这个 https://github.com/fsprojects/FSharp.TypeProviders.StarterPack/issues/68 - user2136963
不,这与问题无关 - 它涉及到_参数化方法_。您可以构建生成类型提供程序,只需在参数化类型和提供的类型上设置IsErased=false即可。 - Tomas Petricek
“生成的”意味着它没有被擦除,对吗? - user2136963
是的,生成的意思是它没有被擦除。 - Tomas Petricek
但是你说“你可以构建生成类型提供程序,只需要IsErased=false”。我可以设置它,将InvokeCode = fun args -> <@@ obj() @@>添加到emptyCtor中,但是typedefof<X>将成为Object,而不是X。我无法通过将它们标记为非生成来构建生成类型提供程序。 - user2136963

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接