Невозможно загрузить сборку, созданную с помощью служб компилятора F #, через отражение - PullRequest
3 голосов
/ 31 октября 2019

Я получаю следующее сообщение об ошибке, когда пытаюсь загрузить (с помощью отражения) .dll, созданную с использованием служб компилятора F # (даже при том, что метод Equals, на который жалуются, существует в сборке):

Unhandled Exception: System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types.
Method 'Equals' in type 'XXX' from assembly 'YYY', Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.
   at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
   at System.Reflection.RuntimeModule.GetTypes()
   at System.Reflection.Assembly.GetTypes()

Я использую .NET Core в Ubuntu.

Однако, если я собираю с использованием кода Visual Studio, я могу загрузить сборку. Я открыл обе сборки и заметил, что у версии, которая не работает, есть переопределение для одного из методов Equals, а у версии, которая работает, нет. Я не уверен, если это имеет значение:

    [CompilerGenerated]
    public sealed bool Equals(object obj, IEqualityComparer comp)

против

    [CompilerGenerated]
    public sealed override bool Equals(object obj, IEqualityComparer comp)

Кроме того, когда я проверяю ссылки с помощью dnSpy, работающая версия имеет ссылку на .netstandard. в то время как версия, которая не имеет этой ссылки. Я попытался добавить ссылку на .netstandard .dll в процессе компиляции, но это, похоже, не дает никакого эффекта.

Код, который я пытаюсь создать, представляет собой простую запись, примерно эквивалентнуюк следующему:

namespace Xxx

open System

type Yyy =
    {
        ServiceCategory : string
        DateRange : DateTime
    }

Вот код, который я использовал для построения с использованием F # Compiler Services:

 // Detect the file location for the library that defines the object type
      let corelibRefLocation = typeof<Object>.GetTypeInfo().Assembly.Location
      let corelibRefDirectory = Path.GetDirectoryName(corelibRefLocation)
      let mscorlibRefLocation = sprintf @"%s/mscorlib.dll" corelibRefDirectory
      let systemRuntimeRefLocation = sprintf @"%s/System.Runtime.dll" corelibRefDirectory
      let netStandardRefLocation = sprintf @"%s/netstandard.dll" corelibRefDirectory

      let staticArgs =
            [|
             "fsc.exe"
             "--noframework"            
             "-o"; outputPath;
             "-a"; sourcePath           
            |]

      let references =
           [|
             "-r"; corelibRefLocation
             "-r"; systemRuntimeRefLocation
             "-r"; mscorlibRefLocation 
             "-r"; netStandardRefLocation 
           |]

      let args = Array.concat([|staticArgs; references|])         

      let errors, exitCode = 
          checker.Compile(args)
           |> Async.RunSynchronously 

      match (errors, exitCode) with
      | [||], 0 -> Console.WriteLine("OK!")
      | _ -> Console.WriteLine("Not OK!")

Я не уверен, почему .dll не загружается и что янужно сделать по-другому.

ОБНОВЛЕНИЕ: Я обновил .net Core 2.1. до .NET Core 3.0, и хотя сгенерированный код больше не включает переопределение, проблема сохраняется. Единственное существенное различие между версией, которая работает (скомпилированной с VSCode), и версией, которая не (скомпилированной с FCS), которую я могу наблюдать сейчас, заключается в том, что версия FCS имеет явную ссылку на mscorlib и System.Private.CoreLib. Тем не менее, я не могу получить код для компиляции без этих явных ссылок.

...