由于 VS2017 中的 F# 编译器过时,无法使用 .dll 库

Failed to use .dll library because of outdated F# compiler in VS2017

较新版本的匿名记录
我有两个版本的私有库:Proxy.1.1.5.dllProxy.2.0.0.dll。 较新的使用 F# 匿名记录。其他差异不是那么重要(我猜)。

等于VS2019构建配置
两个版本均由安装了 Visual Studio 2019GitHub 托管服务器构建并发布到私人 NuGet 提要,基于相同的脚本,因此初始条件相同。没有警告。


VS2017
上的 F# 编译器版本错误 Models 项目使用 Proxy.1.1.5 包(纯 .dll,无源)。它在我的本地机器上由 Visual Studio 2017 完美构建。但是,Proxy.2.0.0 编译失败,原因是:

error FS0229: Error opening binary file 
    'C:\Projects\Dashboard.WPF\packages\Proxy.2.0.0\lib\net462\Proxy.dll':
    Error reading/writing metadata for the F# compiled DLL 
      'C:\Projects\Dashboard.WPF\packages\Proxy.2.0.0\lib\net462\Proxy.dll'.
    Was the DLL compiled with an earlier version of the F# compiler? (
        error: 'lookup_uniq in table istrings out of range, n = 110, sizeof(tab) = 6').

显然,实际上不是较早,而是较新版本


预期行为
我的 Visual Studio 2017 中的 F# 版本不支持匿名记录。 但我希望任何 .dll 都可以用作编译 Models 过时 VS2017 项目的依赖项,只是因为它也是 .dll 而不是 .fs 源来编译它们。 .dll 包含纯 IL 代码,匿名记录在编译期间被编译器生成的 类 替换(因此在创建 .dll 之前)。

问题

  1. 这怎么可能?
  2. 尽管两种情况下的环境条件相同,它是否真的仅根据代码本身选择了 F# 编译器版本?
  3. 如何在不在本地计算机上安装 Visual Studio 2019 的情况下使用 Proxy.2.0.0.dll 版本构建依赖项目 Models
    3.1. fsc.exe --nointerfacedata 有帮助吗?

    Instructs the compiler to omit the resource it normally adds to an assembly that includes F#-specific metadata.

  1. F# 分析 dll 中与 F# 相关的元数据,以便对 F# 对象进行特殊处理。您应该能够很好地使用 C# 中的这些 dll。但是旧的 F# 编译器无法理解新的 F# 编译器生成的元数据。
  2. [没看懂问题。]
  3. 为什么现在要使用 VS2017?删除元数据可能会启用 VS2017 构建,但您将无法以与需要 F# 到 F# 理解的功能相同的方式编译依赖项目,然后将无法在项目之间工作。

不幸的是,无法从不理解匿名记录的旧编译器中使用这样的 .dll。这是因为该功能已添加到 F# 元数据格式,每当使用该功能将新(相对于旧编译器)元数据写入元数据 blob 时,它就会带来破坏前向兼容性的不幸后果。从支持的角度来看,向前兼容性是首选,但不能保证。

这是支持的:

  • 较新的编译器可以使用较旧的编译器生成的二进制文件
  • 较新的编译器可以依赖较旧的 FSharp.Core
  • 较新的编译器可以与较旧的编译器重新绑定 FSharp.Core 而无需重新编译
  • 较旧的编译器可以依赖较新的 FSharp.Core
  • 较旧的编译器可以与较新的编译器重新绑定 FSharp.Core 而无需重新编译

这是经常有效但不保证有效的方法:

  • 较旧的编译器可以使用较新的编译器生成的二进制文件
  • 较旧的编译器可以在较新的 FSharp.Core
  • 中使用 all 构造

注意: 这假设 F# post-.NET Framework 3.5。将 F# 与旧版本的 .NET Framework 一起使用时有一些特殊注意事项。

最后两点不能保证工作的原因是可能有一个新概念,旧的编译器根本无法理解。一个这样的例子是 FSharp.Core 4.5.2 或更高版本中的 voidptr 类型。这是一个新的原语,旧的编译器可能无法正确解释。

不幸的是,每当使用某个功能涉及以旧编译器无法理解的方式写入元数据格式时,这就会让人感到困惑。编译器错误可能应该得到改善。