System.TypeLoadException

The exception that is thrown when type-loading failures occur.

Minimum version: >= 1.1 >= Core 1.0

Statistics

16
elmah.io logo 24

How to handle it

try
{

}
catch (System.TypeLoadException e)
{

}
try
{

}
catch (System.TypeLoadException e) when (e.Message.Contains("something"))
{

}
try
{

}
catch (System.TypeLoadException e) when (LogException(e))
{

}

private static bool LogException(Exception e)
{
    logger.LogError(...);
    return false;
}

How to avoid it

TypeLoadException happens when a type could not be loaded by the CLR. This can be caused by several different issues, but here's a list of things to try out:

  • Locate the DLL file containing the type that could not be loaded in the build folder (typically Debug or Release). Make sure that the DLL files exist.
  • Right-click the DLL file and go to the Details tab and make sure that the DLL has the expected version number.
  • Make sure to use the same version of a NuGet package in all projects.
  • Search the app.config or web.config for any references to the assembly name of the missing type. There may be an unexpected binding redirect set up to the wrong version number.

Links

YouTube videos

Possible fixes from StackOverflow

NOTE - If this answer doesn't help you, please take the time to scroll down through the other answers that people have added since.

Really short answer

Delete all your bin and obj directories and rebuild everything. The versions of the dlls don't match.

Short answer

This can happen if you add a method to an interface in one assembly, and then to an implementing class in another assembly, but you rebuild the implementing assembly without referencing the new version of the interface assembly.

In this case, DummyItem implements an interface from another assembly. The SetShort method was recently added to both the interface and the DummyItem - but the assembly containing DummyItem was rebuilt referencing the previous version of the interface assembly. So the SetShort method is effectively there, but without the magic sauce linking it to the equivalent method in the interface.

Long answer

If you want to try reproducing this, try the following:

  1. Create a class library project: InterfaceDef, add just one class, and build:

     public interface IInterface
     {
         string GetString(string key);
         //short GetShort(string key);
     }
    
  2. Create a second class library project: Implementation (with separate solution), copy InterfaceDef.dll into project directory and add as file reference, add just one class, and build:

     public class ImplementingClass : IInterface
     {
         #region IInterface Members
         public string GetString(string key)
         {
             return "hello world";
         }
    
         //public short GetShort(string key)
         //{
         //    return 1;
         //}
         #endregion
     }
    
  3. Create a third, console project: ClientCode, copy the two dlls into the project directory, add file references, and add the following code into the Main method:

      IInterface test = new ImplementingClass();
      string s = test.GetString("dummykey");
      Console.WriteLine(s);
      Console.ReadKey();
    
  4. Run the code once, the console says "hello world"

  5. Uncomment the code in the two dll projects and rebuild - copy the two dlls back into the ClientCode project, rebuild and try running again. TypeLoadException occurs when trying to instantiate the ImplementingClass.

You can use JetBrains dotPeek (free), Reflector, ILDASM or ILSpy to get the assembly version.

You usually can find ILDASM in C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools\ildasm.exe (where v8.1A is the version of the Windows SDK installed).

ILDASM:

ildasm

Reflector:

reflector

EF calls CreateWebHostBuilder or BuildWebHost without running Main. So Iconfiguration is null.

Create new class which inherited from IDesignTimeDbContextFactory .

public class YourDbContext : DbContext
{
//Dbcontext implementation
}

public class YourDbContextFactory : IDesignTimeDbContextFactory<YourDbContext>
{
    public YourDbContext CreateDbContext(string[] args)
    {
        var optionsBuilder = new DbContextOptionsBuilder<YourDbContext>();
        optionsBuilder.UseSqlServer("your connection string");

        return new YourDbContext(optionsBuilder.Options);
    }
}

You are using a new .net core EF which uses IHostBuilder.(in an older version like yours the provider is IWebHostBuilder).

The tools first try to obtain the service provider by invoking the Program.CreateHostBuilder(), calling Build(), then accessing the Services property.

You can learn more about Design-time DbContext Creation from Here

It may happen from a condition in your startup file or while you are injecting. for example, you have a flag that checks if some variable in appsettings is true to use inmemory database instance.

EF needs to build the model and use the DbContext without starting the application. When EF invokes methods, your config services are still null that's why you get an error.

Make sure you have installed the package

Microsoft.EntityFrameworkCore.Tools

As the accepted answer suggested:

EF calls CreateWebHostBuilder or BuildWebHost without running Main. So Iconfiguration is null.

But instead of using a more complex factory, You can use this simple solution by overriding OnConfiguring.

public class ApplicationDbContext : DbContext
{        
    public ApplicationDbContext() {
        
    }
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
    {            
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
            optionsBuilder.UseSqlServer("Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=Chinook");
        }
    }

*Pay attention for not using the db connection string inside the source code (docs)

dotnet user-secrets set ConnectionStrings:Chinook "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Chinook"
dotnet ef dbcontext scaffold Name=ConnectionStrings:Chinook Microsoft.EntityFrameworkCore.SqlServer

also pay attention to use only one \ in the cli command line.

If you know Class, that belongs to assembly, you can use GetTypeInfo

var runtimeVersion = typeof(MyClass)
.GetTypeInfo()
.Assembly
.GetCustomAttribute<AssemblyFileVersionAttribute>();

var version = runtimeVersion.Version;

 

The example is for .Net Core from https://developers.de/blogs/damir_dobric/archive/2017/06/27/how-to-deal-with-assembly-version-in-net-core.aspx