Метаданные F # Powerpack не распознают FSharp.Core как библиотеку F # - PullRequest
2 голосов
/ 27 мая 2010

Вот мой тестовый код для выявления проблемы:

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. Я не получаю ошибку в FSI после выполнения #r "@C:\Program Files...\FSharp.Powerpack.Metadata.dll".

Есть идеи? Я использую Visual Studio 2008, F # 2.0 и F # Powerpack 2.0.0.0 (20 мая 2010 г.) на старой версии виртуальной машины XP, но, думаю, она обновлена ​​до 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 ]

3 голосов
/ 01 июня 2010

Я нашел непосредственную причину проблемы, прочитав источник Powerpack на Codeplex . Powerpack.Metadata всегда загружает FSharp.Core перед любой другой сборкой, поэтому, если она сломана, она блокирует остальные.

Из моего исследования большинство других сборок F # переносят свои метаданные с собой в поток ресурсов манифеста с именем "FSharpSignatureData. Package.Name " - вот где библиотека метаданных выглядит первой. Но FSharp.Core не делает. (По крайней мере, на моей виртуальной машине XP загрузка 2.0.0.0 для VS 2008 этого не делает.) Таким образом, метаданные Powerpack ищут файл с именем FSharp.Core.sigdata в том же каталоге, где он ожидает найти файл FSharp.Core.dll.

Код ищет четыре места для этого имени каталога:

  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 года.
  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. Мой локальный проект не имеет копии FSharp.Core.sigdata в каталоге bin / Debug.

Теперь, когда я знаю, что происходит, у меня есть ряд исправлений (помимо использования реальной машины с 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 голосов
/ 04 июня 2010

Натан, большое расследование, номер версии действительно не обновлялся в оригинальном выпуске за май 2010 года, см. http://fsharppowerpack.codeplex.com/workitem/4548 Мы загрузили двоичные файлы с исправленным номером версии.

1 голос
/ 27 мая 2010

Это действительно сбивает с толку - я попытался запустить код, используя точный сценарий, который вы описали (F # 2.0 в Visual Studio 2008, с последней версией PowerPack 2.0 от CodePlex), и он работает без каких-либо исключений.

Вы также можете убедиться, что у вас установлена ​​последняя версия F # для Visual Studio 2008 (выпущенная вскоре после финальной версии Visual Studio 2010), поскольку загружаемое FSharp.Core.dll должно быть совместимо с * 1004. *. Кроме того, может ли библиотека Metadata загружать другие библиотеки dll, которые вы компилируете с текущей версией компилятора F #?

EDIT Если это не сработает, то (я думаю) библиотека 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
...