在F#类型提供程序中发出生成的类型

4
我创建了一个简单的生成类型提供程序,它接受一个程序集的路径并重新组织类型,使它们属于类型提供程序命名空间(类似于内部化)。
相关代码链接在这里: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'时出现问题:类型Program的pass3中出现错误,错误:GetMethodRefAsMethodDefIdx中mref=".ctor"时出现错误,错误:抛出了'Microsoft.FSharp.Compiler.AbstractIL.ILBinaryWriter+MethodDefNotFound'类型的异常。 FSC 1 1 TypeProviders.Tests

samples pack提供的生成类型示例中,似乎没有定义任何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

提前感谢

1个回答

4

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

我认为在这里,您不需要创建生成的类型来包装现有类型 => 这应该可以工作。

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

天啊,我真是太蠢了,我本来就试过那个方法,但是在我的代码中直接引用了生成的类型,所以后来出现了编译错误。教训就是要认真阅读错误信息。再次感谢。 - Colin Bull

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