这是我的测试代码,用于隔离问题:
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#程序集的异常(下面的详细信息,为了可读性而重新格式化)。还有两条线索:
core3
方法,我得到了测试F#程序集本身的相同错误#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 . . .
答案 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的文件。
代码查找此目录名称的四个位置:
@"SOFTWARE\Microsoft\.NETFramework\" + MSCorLibRunningRuntimeVersion + @"\AssemblyFoldersEx\Microsoft Visual F# 4.0"
,其中MSCorLibRunningRuntimeVersion由反射决定 - 在我的例子中它是“v2.0.50727”。我认为这只适用于你有VS 2010,因此有F#4.0 @"Software\Microsoft\.NETFramework\AssemblyFolders\Microsoft.FSharp-" + FSharpTeamVersionNumber
,其中FSharpTeamVersionNumber 硬编码为“1.9.9.9”,至少在codeplex版本中。我没有在我的机器上安装2010年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)
答案 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