在F#类型提供程序中发出生成的类型 [英] Emitting Generated Types in F# type providers

查看:84
本文介绍了在F#类型提供程序中发出生成的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个简单的生成类型提供程序,该程序在重新组合类型时采用程序集的路径,以将它们置于类型提供程序命名空间下(如果需要,可以进行内部化处理).

有关代码的链接在这里 https://github.com/colinbull/Playground

现在似乎可以正确提供类型了,

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

因为VS中的显示没有任何报告的错误.但是,当我编译该程序集时,IL似乎被错误地发出,并带有以下错误.

错误1:写入二进制文件'obj \ Debug \ TypeProviders.Tests.exe'时出现问题:类型3的程序类型错误,错误:mref =".ctor"的GetMethodRefAsMethodDefIdx错误,错误:类型'异常抛出Microsoft.FSharp.Compiler.AbstractIL.ILBinaryWriter + MethodDefNotFound. FSC 1 1 TypeProviders.Tests

示例包中给出的生成类型的示例似乎定义了任何StaticParameters,要求返回具有提供的类型名称的类型.在这种情况下,如何在提供的程序集中发出类型?目前,我正在执行以下操作

  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

预先感谢

解决方案

免责声明:浏览器编译的解决方案

我相信在这里您不需要创建生成的类型来包装现有的类型=>这样就可以了

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

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

    reqType

您也可以尝试以下方法:

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

这将保留名称空间,因此类型C的声明应如下

type C = T.SimpleLib.Class1

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

解决方案

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

这篇关于在F#类型提供程序中发出生成的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆