【问题标题】:F# Powerpack's Metadata doesn't recognize FSharp.Core as an F# libraryF# Powerpack 的元数据无法将 FSharp.Core 识别为 F# 库
【发布时间】:2011-02-24 16:46:36
【问题描述】:

这是我用来隔离问题的测试代码:

open Microsoft.FSharp.Metadata
[<EntryPoint>]
let main args =
  let core = FSharpAssembly.FromFile @"C:\Program Files\FSharp-2.0.0.0\\bin\FSharp.Core.dll"
  let core2 = FSharpAssembly.FSharpLibrary
  let core3 = System.AppDomain.CurrentDomain.GetAssemblies() 
              |> Seq.find (fun a -> a.FullName.Contains "Core") 
              |> FSharpAssembly.FromAssembly

  core.Entities |> Seq.iter (printfn "%A")
  0

所有三个lets 都应该给我相同的 FSharpAssembly。相反,所有 3 都抛出 FSharp.Core 不是 F# 程序集的异常(详情如下,为便于阅读重新格式化)。还有两条线索:

  1. 使用core3 方法,测试F# 程序集本身出现相同的错误
  2. 执行#r "@C:\Program Files...\FSharp.Powerpack.Metadata.dll" 后,我在 FSI 没有收到错误。

有什么想法吗?我在旧的 XP VM 上使用 Visual Studio 2008、F# 2.0 和 F# Powerpack 2.0.0.0(2010 年 5 月 20 日)版本,但我认为它已更新到 SP3。

(今天早上我收到了 Powerpack 1.9.9.9 的错误,所以我升级到 2.0.0.0。我想如果 1.9.9.9 不能识别 F# 的 2.0.0.0 的程序集,那么可能是 Powerpack 2.0 中的错误修复。 0.0 会有所帮助。)

Unhandled Exception: System.TypeInitializationException: 
  The type initializer for 'Microsoft.FSharp.Metadata.AssemblyLoader' threw an
    exception. 
  ---> System.TypeInitializationException: The type initializer for
    '<StartupCode$FSharp-PowerPack-Metadata>.$Metadata' threw an exception. 
  ---> System.ArgumentException: could not produce an FSharpAssembly 
    object for the assembly 'FSharp.Core' because 
    this is not an F# assembly
Parameter name: name
   at Microsoft.FSharp.Metadata.AssemblyLoader.Add(String name,Assembly assembly)
   at <StartupCode$FSharp-PowerPack-Metadata>.$Metadata..cctor()
   --- End of inner exception stack trace ---
   at Microsoft.FSharp.Metadata.AssemblyLoader..cctor()
   --- End of inner exception stack trace ---
   at Microsoft.FSharp.Metadata.AssemblyLoader.Get(Assembly assembly)
   at Microsoft.FSharp.Metadata.FSharpAssembly.FromAssembly(Assembly assembly)
   at Program.main(String[] args) in 
     C:\Documents an...\FSMetadataTest\Program.fs:line 11
Press any key to continue . . .

【问题讨论】:

    标签: f# metadata powerpack


    【解决方案1】:

    这真的令人困惑 - 我尝试使用您描述的确切场景(Visual Studio 2008 中的 F# 2.0,使用 CodePlex 的最新 PowerPack 2.0)运行代码,并且它没有任何例外地工作。

    您还可以确保您拥有最新版本的 F# for Visual Studio 2008(在 Visual Studio 2010 最终版本之后不久发布),因为您正在加载的 FSharp.Core.dll 需要与 @987654322 兼容@。另外,Metadata 库是否能够加载您使用当前版本的 F# 编译器编译的其他 dll 库?

    编辑 如果这不起作用,那么(我认为)Metadata 库可能与 F# 编译器不同步:

    let a = System.Reflection.Assembly.GetExecutingAssembly()
         |> FSharpAssembly.FromAssembly
    printf "%A" a.Entities.Count
    

    如果以下内容不起作用,那将是真正令人困惑的 - 无论是什么版本,库都应该能够自行读取!

    let a = FSharpAssembly.FromFile @"C:\...\bin\FSharp.PowerPack.Metadata.dll"
    printf "%A" a.Entities.Count
    

    【讨论】:

    • 回答你的最后一个问题:没有。至少当我在当前加载的程序集上尝试FromAssembly 时不是这样。我会检查更新版本的 F#。
    • @Nathan:您还可以尝试Metadata 库是否能够读取自身 - 我认为这应该可以。
    • 好点。我也会检查的。我重新安装了 F#,没有任何区别,所以我正在运行 Windows 更新,获得 .NET 2.0 和 3.0 的 SP2。不是我希望它有帮助,但谁知道呢。
    • 好吧,这很烦人:当Metadata 尝试为FSharp.Core 加载 FSharpAssembly 时,你的两个 sn-ps 都失败了。所以显然你不能避免加载FSharp.Core,即使你请求加载其他东西。
    • @Nathan:是的,我猜FSharp.Core 是在模块的初始化程序中加载的(所以当你从Metadata 访问任何东西时它会急切地加载)。这有点不幸,但可能需要......
    【解决方案2】:

    我通过阅读Powerpack source on Codeplex 找到了问题的直接原因。 Powerpack.Metadata 总是在任何其他程序集之前加载 FSharp.Core,因此如果它被破坏,它会阻止其余的程序。

    根据我的研究,大多数其他 F# 程序集都在名为“FSharpSignatureData.Package.Name”的清单资源流中携带其元数据——这是元数据库首先出现的地方。但 FSharp.Core 没有。 (至少,在我的 XP VM 上,VS 2008 的 2.0.0.0 下载没有。)因此,Powerpack 元数据在它期望找到 FSharp.Core.dll 的同一目录中查找名为 FSharp.Core.sigdata 的文件。

    代码在四个位置查找此目录名称:

    1. ConfigurationSettings.AppSettings.["fsharp-core-referenceassembly-location"].
    2. 注册表项@"SOFTWARE\Microsoft\.NETFramework\" + MSCorLibRunningRuntimeVersion + @"\AssemblyFoldersEx\Microsoft Visual F# 4.0",其中 MSCorLibRunningRuntimeVersion 由反射确定——在我的例子中是“v2.0.50727”。我认为这只适用于你有 VS 2010 和 F# 4.0
    3. 至少在 codeplex 版本中,注册表项 @"Software\Microsoft\.NETFramework\AssemblyFolders\Microsoft.FSharp-" + FSharpTeamVersionNumber,其中 FSharpTeamVersionNumber硬编码为“1.9.9.9”。我的机器上没有安装 2010 年 5 月版本的源代码。
    4. System.AppDomain.CurrentDomain.BaseDirectory。这是您本地项目的“bin/Debug”目录,除非您在 fsi 中。然后是 C:\Program Files\FSharp-2.0.0.0\bin 的一些变体。

    对我来说,四个都失败了:

    1. 我没有应用程序配置文件。我不太了解 .NET 生态系统,所以不知道如何创建一个。
    2. 我没有安装 VS 2010。
    3. 我在正确的位置有一个“Microsoft.FSharp-2.0.0.0”键,但没有“Microsoft.FSharp-1.9.9.9”键。
    4. 我的本地项目在 bin/Debug 目录中没有 FSharp.Core.sigdata 的副本。

    现在我知道发生了什么,我有一些修复(除了使用真正的 Windows 机器而不是古老的虚拟机,我计划在大约一个月内修复)。无论如何,我应该可能了解 .NET 的配置文件,所以这可能是最好的中期解决方案。创建注册表项“Microsoft.FSharp-1.9.9.9”或将 FSharp.Core.sigdata 复制到 bin/Debug 目录是一个超级简单的短期修复。

    我仍然不知道这个错误是否应该普遍存在,或者它是否只是由我从 VS 2005->2008 升级和多个 F# 预览引起的。通过阅读 codeplex 源,在我看来,其他没有 VS 2010 的人也应该有这个问题,只是因为 FSharpTeamVersionNumber 被硬编码为 1.9.9.9,并且尚未更新以匹配注册表项 2.0.0.0。但也许我升级到 F# 2.0 和 F# Powerpack 2.0 的顺序错误地混合在一起产生了这种情况。或者可能没有足够的人使用元数据库来暴露这个错误。

    【讨论】:

      【解决方案3】:

      Nathan,很好的调查,版本号在原来 May2010 发布时确实没有更新,见http://fsharppowerpack.codeplex.com/workitem/4548 我们已上传具有更正版本号的二进制文件。

      【讨论】:

        猜你喜欢
        • 2013-08-10
        • 2011-07-02
        • 2011-09-02
        • 2012-01-01
        • 2011-10-09
        • 1970-01-01
        • 2012-12-11
        • 1970-01-01
        • 2023-03-25
        相关资源
        最近更新 更多