3

I keep getting the following error message when I tried to load (via reflection) a .dll built using F# compiler services (even though the Equals method being complained about does exist in the build):

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()

I'm using .NET Core on Ubuntu.

However, if I build using Visual Studio Code, I'm able to load the assembly. I opened both builds and I noticed the version that doesn't work has an override for one of the Equals method while the version that does, doesn't. I'm not sure if this is of consequence:

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

vs

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

Additionally, when I check the references using dnSpy, the version that works has a reference to .netstandard while the version that does not does not have this reference. I've tried adding a reference to the .netstandard .dll as part of the compilation but this doesn't seem to have any effect.

The code I'm trying to build is a simple record, roughly equivalent to the following:

namespace Xxx

open System

type Yyy =
    {
        ServiceCategory : string
        DateRange : DateTime
    }

Here's the code I used to build using 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!")

I'm not sure why the .dll isn't loading and what I need to do differently.

UPDATE: I've upgraded from .net Core 2.1. to .NET Core 3.0 and even though the generated code now no longer includes the override, the issue persists. The only significant difference between the version that works (compiled with VSCode) and the version that doesn't (compiled with FCS) that I can observe now is that the FCS version has an explicit reference to mscorlib and System.Private.CoreLib. However, I'm unable to get the code to compile without these explicit references.

Tolu
  • 1,081
  • 1
  • 8
  • 23
  • Think you might need to include version numbers, the approach you use to `build using Visual Studio Code`, and the way you `built using F# compiler services`. – drkmtr Oct 31 '19 at 18:04
  • Thanks @drmtr, I've updated to show my F# compiler services code – Tolu Oct 31 '19 at 18:18
  • This is just a guess but assembly load contexts could be something to look at as if the wrong one is used it can give odd type errors: https://learn.microsoft.com/en-us/dotnet/framework/deployment/best-practices-for-assembly-loading – Just another metaprogrammer Nov 03 '19 at 06:46
  • @Justanothermetaprogrammer. Thanks for the feedback. However, it's very unlikely this is the issue as I'm able to load the same code - but compiled using VSCode - with the same load context. – Tolu Nov 04 '19 at 11:32
  • @Justanothermetaprogrammer. Could you post this as an answer so you'd be eligiblle for the bounty when it expires in 2 days. No one else has posted an answer and I'd not want the bounty to go un-awarded in case I don't get an answer before the bounty expires. I've re-implemented my code in some other way to get around this issue. – Tolu Nov 07 '19 at 10:00

0 Answers0