Emitting Generated Types in F# type providers

谁说我不能喝 提交于 2019-12-12 14:00:27

问题


I have created a simple generating type provider that takes the path to an assembly at reorganizes the types, to bring them under the type providers namespace, (sort of Internalising if you like).

The link to the code concerned is here https://github.com/colinbull/Playground

Now the types seem to be provided correctly,

let[<Literal>]assemblyPath = @"D:\Appdev\Playground\SimpleLib\bin\Debug\SimpleLib.dll"
type T = Inno.InternalisingProvider<assemblyPath>
type C = T.Class1

[<EntryPoint>]
let main argv = 
    let c = new C()
    printfn "Result: %A" c.X
    System.Console.ReadLine() |> ignore
    0

since the displays in VS without any reported errors. However when I compile this assembly the IL seems to get emitted incorrectly with the following error.

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

Examples given for generated types given in samples pack doesn't seem to have any StaticParameters defined which requires a type with the provided type name to be returned. In this case how do I emit the types in the provided assembly? Currently I am doing the following

  let provideAssembly (reqType:ProvidedTypeDefinition) assemblyPath =
      let name = Path.GetFileName(assemblyPath)
      let providedAssembly = ProvidedAssembly.RegisterGenerated(assemblyPath)

      for t in providedAssembly.GetExportedTypes() do
          let ty = createGeneratedType t
          ty.SetAssembly(providedAssembly)
          reqType.AddMember(ty)

      reqType

Thanks in advance


回答1:


Disclaimer: browser compiled solutions

I believe here you don't need to create generated types that will wrap exiting types => this should work

let provideAssembly (reqType:ProvidedTypeDefinition) assemblyPath =
    let existingAssembly = Assembly.LoadFrom(assemblyPath)

    for ty in providedAssembly.GetExportedTypes() do
        reqType.AddMember(ty)

    reqType

You can also try this one:

let provideAssembly (reqType:ProvidedTypeDefinition) assemblyPath =
    reqType.AddAssemblyTypesAsNestedTypesDelayed(fun() -> Assembly.LoadFrom assemblyPath)
    reqType

this one will preserve namespace so declaration of type C will look like

type C = T.SimpleLib.Class1


来源:https://stackoverflow.com/questions/15078419/emitting-generated-types-in-f-type-providers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!