F# собирают код в концах во время выполнения на недостающих собраниях

Мне связали вопрос с кодом, предоставленным в ответе на этот вопрос.

Проблема, которую я имею, состоит в том, что три сослались на assmeblies (System.dll, Фа-диез. Core.dll, Фа-диез. Powerpack.dll), которые передаются, чтобы CompilerParameters , не найдены во времени выполнения. Ошибка, которую я получаю:

неизвестный файл (0,0): ошибка 0: ошибка FS0218: Неспособный прочитать собрание 'Студия c:\user s\utente\documents\visual 2010\Projects\TrashSolution\TrashSolution\bin\D ebug\FSharp. Core.dll'

Как я говорю компилятору искать эти собрания в GAC вместо каталога bin проекта? Если я открываю пространство имен в коде, предоставленном как последовательность, как я знаю который собрания добавить? Где я могу получить эту информацию?

3
nl ja de

1 ответы

В коде из ответа вы связались, есть линия к основанию:

let asm = Reflection.Assembly.LoadFrom(fileinfo.Value.FullName)

Если вы звоните Отражение. Груз вместо этого и проход это , полностью квалифицированные имя сборки, это попытается загрузить собрание от GAC (и несколько других мест, если собрание не будет в GAC).

let asm =
    Assembly.Load "SampleAssembly, Version=1.0.2004.0, Culture=neutral, PublicKeyToken=8744b20f8da049e3"

Если вы не знаете полностью квалифицированного имени сборки, необходимо создать AssemblyName с простым названием собрания, затем звонить Отражение. Груз перегрузка, которая берет AssemblyName вместо последовательность .

let asmName = AssemblyName "Your.Assembly.Name"
let asm = Assembly.Load asmName

До знания, какие собрания загрузить - я не думаю, есть простой способ определить это программно. Эти только два решения я могу думать прямо сейчас:

  1. , Если у вас есть некоторые знание о коде, вам дают (как последовательность), вы могли разобрать его с FSharpCodeProvider и взгляд, какие пространства имен/модули открыты и какие типы используются. Если вы надеетесь видеть, используются ли некоторое конкретное пространство имен или тип (т.е., для которого необходимо было бы включать ссылку на сборку, собирая код), вы могли создать Карту (в вашем .fsx , который делает компиляцию) пространств имен и/или имен типов к именам сборки, и используйте его, чтобы сослаться на соответствующие собрания.
  2. , который Вы могли поиск "в лоб" GAC, при помощи полузарегистрированного API Сплава, чтобы перечислить все собрания, установленные в GAC, затем используя Отражение, чтобы исследовать каждое собрание и определить, является ли это то, вы требуете. Это, вероятно, будет чрезвычайно медленно, таким образом, я избежал бы его любой ценой. Если вы действительно решаете пойти этот маршрут, вы должны , также используют Ассамблею. ReflectionOnlyLoad метод, чтобы загрузить собрания! Это позволяет собраниям быть разгруженными после того, как вы заканчиваете исследовать их - если вы используете нормальное Отражение, собрания не могут быть разгружены, и ваша программа, вероятно, потерпит крах с OutOfMemoryException или подобный.

EDIT: Turns out that loading the assembly by its simple name succeeds in fsi and not in normal F# code because fsi automatically installs a handler for the AppDomain.AssemblyResolve event. This event is triggered by the CLR when you try to load an assembly and it can't be resolved; the event provides a way for you to "manually" resolve the assembly and/or generate an assembly dynamically and return it.

Если вы посмотрите на FileNotFoundException поднятый, когда вы попытаетесь управлять кодом в проекте F#, вы будете видеть что-то вроде этого в собственности Журнала Сплава исключения:

=== Pre-bind state information ===
LOG: User = Jack-Laptop\Jack
LOG: DisplayName = System
 (Partial)
WRN: Partial binding information was supplied for an assembly:
WRN: Assembly Name: System | Domain ID: 1
WRN: A partial bind occurs when only part of the assembly display name is provided.
WRN: This might result in the binder loading an incorrect assembly.
WRN: It is recommended to provide a fully specified textual identity for the assembly,
WRN: that consists of the simple name, version, culture, and public key token.
WRN: See whitepaper http://go.microsoft.com/fwlink/?LinkId=109270 for more information and common solutions to this issue.
LOG: Appbase = file:///C:/Users/Jack/Documents/Visual Studio 2010/Projects/StackOverflow1/StackOverflow1/bin/Debug/
LOG: Initial PrivatePath = NULL
Calling assembly : StackOverflow1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/Users/Jack/Documents/Visual Studio 2010/Projects/StackOverflow1/StackOverflow1/bin/Debug/System.DLL.
LOG: Attempting download of new URL file:///C:/Users/Jack/Documents/Visual Studio 2010/Projects/StackOverflow1/StackOverflow1/bin/Debug/System/System.DLL.
LOG: Attempting download of new URL file:///C:/Users/Jack/Documents/Visual Studio 2010/Projects/StackOverflow1/StackOverflow1/bin/Debug/System.EXE.
LOG: Attempting download of new URL file:///C:/Users/Jack/Documents/Visual Studio 2010/Projects/StackOverflow1/StackOverflow1/bin/Debug/System/System.EXE.

Смотря на основание той регистрации, вы будете видеть, где CLR искал собрание, прежде чем это сдалось.

Вот простой укладчик, чтобы дать вам общее представление о том, как использовать AppDomain. Укладчик AssemblyResolve, чтобы вручную решить собрание. (ОТМЕТЬТЕ: укладчик должен быть добавлен прежде код, который пытается загрузить собрание!)

System.AppDomain.CurrentDomain.add_AssemblyResolve (
    System.ResolveEventHandler (fun _ args ->
        let resolvedAssembly =
            System.AppDomain.CurrentDomain.GetAssemblies ()
            |> Array.tryFind (fun loadedAssembly ->
               //If this assembly has the same name as the one we're looking for,
               //assume it's correct and load it. NOTE : It may not be the _exact_
               //assembly we're looking for -- then you'll need to adjust the critera below.
                args.Name = loadedAssembly.FullName
                || args.Name = loadedAssembly.GetName().Name)

       //Return null if the assembly couldn't be resolved.
        defaultArg resolvedAssembly null))

Если вы добавляете, что код к новому проекту пульта F#, сопровождаемому кодом, который использует, AssemblyName с Ассамблеей. Груз, необходимо быть в состоянии загрузить Систему собрание, потому что на это ссылаются по умолчанию в проекте F#, и это будет загружено, когда вы будете управлять проектом. При попытке решить Систему. Таща , это потерпит неудачу, потому что наш таможенный обработчик событий не может найти собрание. Очевидно, если вам нужна некоторая более сложная решающая собрание логика, необходимо встроить, это в обработчик событий любым способом имеет смысл для заявления.

Наконец, вот связь с отчетом MSDN, упомянутым в сообщении об исключении: Методы наиболее успешной практики для погрузки Ассамблеи. Это стоящее прочитанного, если вы застреваете и не можете выяснить, как решить собрания, в которых вы нуждаетесь.

7
добавлено
Я добавил некоторую дополнительную информацию к своему ответу о почему you' ре, которое в состоянии решить собрание в fsi а не в обычном проекте.
добавлено автор Jack P., источник
Большое спасибо за ваше объяснение. Однако я заметил некоторые странные вещи. Каким образом, если я пишу Ассамблею. Груз (AssemblyName ("Система"));; в интерактивном пульте F# я получаю требуемое собрание, но когда я пишу тот же самый код в .fs файле и управляю им, я добираюсь, "Не мог загрузить файл или собрание ' System' или одна из его зависимостей. Система не может счесть файл определенным". ошибка? Конечно, и во мне открытая система и в Системе. Отражение.
добавлено автор MSX, источник
Много большое спасибо! Я думаю I' ll тщательно читают обеспеченную связь на MSDN, чтобы понять what' s продолжающийся позади.
добавлено автор MSX, источник
Microsoft Stack Jobs
Microsoft Stack Jobs
1 788 участник(ов)

Work & freelance only Microsoft Stack. Feed https://t.me/Microsoftstackjobsfeed Чат про F#: @Fsharp_chat Чат про C#: @CSharpChat Чат про Xamarin: @xamarin_russia Чат общения:@dotnettalks

F# Chat
F# Chat
835 участник(ов)

fsharplang.ru Правила: https://t.me/fsharp_chat/26609 Новости: @fsharp_news F# в Gitter: gitter.im/fsharplang_ru Поиск функций: @fsdnbot Флудилка: @fsharp_flood Вакансии: @microsoftstackjobs Ссылки: @reasonml_ru @pro_net

Microsoft Developer Community Chat
Microsoft Developer Community Chat
584 участник(ов)

Чат для разработчиков и системных администраторов Microsoft Developer Community. __________ Новостной канал: @msdevru __________ Баним за: оскорбления, мат, рекламу, флуд, флейм, спам, NSFW контент, а также большое количество оффтоп тем. @banofbot

F# Flood: Год комбинаторов
F# Flood: Год комбинаторов
110 участник(ов)

F# флудилка @Fsharp_chat - основной https://t.me/vshapenko_builders Билдеры Василия