fp | FP‎ > ‎fp | F#‎ > ‎f# | type provider‎ > ‎

f#.tp | Type provider causes compiler error

http://social.msdn.microsoft.com/forums/windowsazure/zh-cn/3345cc79-b393-4cd3-8ae2-2ec8da5b8285/type-provider-causes-compiler-error

Type provider causes compiler error 

    问题

  • I'm developing a (not erased) type provider that generate several dozens of types from DB schema. All of them derive from a single base type and call its constructor. Number of constructor arguments varies from type fo type. 

    In design time everything is ok, but when I try to compile a project that uses the TP, I get the following error:

    Error 21  A problem occurred writing the binary 'obj\Debug\xxx.exe': Error in pass3 for type xxx.Fnf, error: Error in GetMethodRefAsMethodDefIdx for mref = ".ctor", error: Exception of type 'Microsoft.FSharp.Compiler.AbstractIL.ILBinaryWriter+MethodDefNotFound' was thrown.

    So, the question is: what theoretically could cause such an error?

    Thanks!

    2013年8月2日 16:48

全部回复

  • OK, I've solved the issue. It turned out that we must create ProvidedAssembly inside DefineStaticParameters() callback method, not outside it.

    Wrong:

    [<TypeProvider>]
    type public TypeProvider1() as this =
        inherit TypeProviderForNamespaces()
        // this is wrong place to create the assembly!
        let assembly = ProvidedAssembly (System.IO.Path.ChangeExtension(System.IO.Path.GetTempFileName(), ".dll"))
        // ...other standard stuff here...
        let newT = ProvidedTypeDefinition(thisAssembly, rootNamespace, "TypeProvider1", Some baseTy)
        let staticParams = [ProvidedStaticParameter("param1", typeof<string>)]
    
        do newT.DefineStaticParameters(
            parameters=staticParams,
            instantiationFunction=(fun typeName paramValues ->
                match paramValues with
                | [| :? string as param1 |] ->
                    let ty = ProvidedTypeDefinition(
                                thisAssembly,
                                rootNamespace,
                                typeName,
                                Some baseTy,
                                HideObjectMethods=true)
            // ...add method, properties and the like...
            // finally, add the type into the assembly
            do assembly.AddTypes [newT])

    Right:

    [<TypeProvider>]
    type public TypeProvider1() as this =
        inherit TypeProviderForNamespaces()
        // ...standard stuff here as before...
        let newT = ProvidedTypeDefinition(thisAssembly, rootNamespace, "TypeProvider1", Some baseTy)
        let staticParams = [ProvidedStaticParameter("param1", typeof<string>)]
    
        do newT.DefineStaticParameters(
            parameters=staticParams,
            instantiationFunction=(fun typeName paramValues ->
                match paramValues with
                | [| :? string as param1 |] ->
                    let ty = ProvidedTypeDefinition(
                                thisAssembly,
                                rootNamespace,
                                typeName,
                                Some baseTy,
                                HideObjectMethods=true)
            // ...add method, properties and the like...
            // we must create the assembly here, inside the callback
            let assembly = ProvidedAssembly (System.IO.Path.ChangeExtension(System.IO.Path.GetTempFileName(), ".dll"))
            // then add the type into it
            do assembly.AddTypes [newT])

    After this change several types of this TP can be declared in same project without any problem.

Comments