F#Powerpack的元数据不会将FSharp.Core识别为F#库

时间:2010-05-27 14:13:56

标签: f# metadata powerpack

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

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

所有三个let都应该给我相同的FSharpAssembly。相反,所有3个抛出FSharp.Core不是F#程序集的异常(下面的详细信息,为了可读性而重新格式化)。还有两条线索:

  1. 使用core3方法,我得到了测试F#程序集本身的相同错误
  2. 执行#r "@C:\Program Files...\FSharp.Powerpack.Metadata.dll"后,我在FSI没有收到错误。
  3. 有什么想法吗?我在旧版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 . . .
    

3 个答案:

答案 0 :(得分:3)

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

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

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

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

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

    1. 我没有应用配置文件。我不太了解.NET生态系统,所以我不知道如何创建它。
    2. 我没有安装VS 2010。
    3. 我在正确的位置有一个“Microsoft.FSharp-2.0.0.0”密钥,但没有“Microsoft.FSharp-1.9.9.9”密钥。
    4. 我的本地项目在bin / Debug目录中没有FSharp.Core.sigdata的副本。
    5. 现在我知道发生了什么,我有很多修复(除了使用真正的Windows机器而不是古老的VM,我打算在大约一个月内修复)。我应该可能在某些时候了解.NET的配置文件,所以这可能是最好的中期解决方案。创建注册表项“Microsoft.FSharp-1.9.9.9”或将FSharp.Core.sigdata复制到bin / Debug目录是一个非常简单的短期修复。

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

答案 1 :(得分:3)

内森,非常好的调查,版本号确实没有在最初的May2010版本中更新,请参阅http://fsharppowerpack.codeplex.com/workitem/4548 我们上传了带有更正版本号的二进制文件。

答案 2 :(得分:1)

这实在令人困惑 - 我尝试使用您描述的确切方案运行代码(Visual Studio 2008中的F#2.0,使用CodePlex中的最新PowerPack 2.0),它没有任何例外。

您还可以确保您拥有最新版本的F#for Visual Studio 2008(在Visual Studio 2010的最终版本之后不久发布),因为您加载的FSharp.Core.dll需要与之兼容FSharp.PowerPack.Metadata.dll。此外,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