Alwyn
Alwyn

Reputation: 8337

Assembly.GetTypes() throwing an exception

What does assembly GetTypes() do behind the scenes? Assuming an assembly has been loaded to the AppDomain does it still need to read from the physical DLL? And what the assembly manifest do?

Iterating through the assembly like this:

AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes()) 

I'm occasionally getting the following error:

 Could not load file or assembly 

Which tells me that because an assembly is loaded into the AppDomain it's not necessarily fully loaded to memory. Sometimes it still needs to go back to the file.

My questions:

  1. Why is it doing that?
  2. What can I do to detect these semi-loaded assemblies?

Upvotes: 33

Views: 21999

Answers (3)

NavidM
NavidM

Reputation: 1815

This question is a bit old, but leaving a note here that GetTypes might throw an exception if the application has not loaded the assembly dependencies especially in the newer .NET Core/.NET 5/6 .dlls.

Microsoft has introduced{assemblyName}.deps.json file which contains dependencies for an assembly, so you will need to load those too before you can call GetTypes without getting an exception. I found these blog posts to be helpful on how to do that:

Upvotes: 1

João Angelo
João Angelo

Reputation: 57728

Getting a type from a assembly may require additional assemblies to be loaded so that is most probably the reason for the error; a failure to load a dependent assembly. However a .NET assembly may be constructed from several modules in different files so I believe you may also face this problem if you have a multifile assembly and one or more of the files are missing or corrupt.

Associated with the error you should get more information about the specific assembly that could not be loaded.

If you just want to load a list of the loadable types in the assembly you can use a extension method like this:

public static IEnumerable<Type> GetLoadableTypes(this Assembly assembly)
{
    if (assembly == null) throw new ArgumentNullException(nameof(assembly));
    try
    {
        return assembly.GetTypes();
    }
    catch (ReflectionTypeLoadException e)
    {
        return e.Types.Where(t => t != null);
    }
}

(Source: Get All Types in an Assembly)

Upvotes: 59

DelegateX
DelegateX

Reputation: 719

Behind the scenes, GetType method returns the address stored in the specified object's type object pointer member (When the object is stored in the heap, this information is stored along with couple of others like Sync Block Index). This is how the GetType method returns the true type of any object. An assembly might be dependent on some other assembly that must be loaded. And unless it is required by the application, it won't be loaded by JIT. So, yes, it requires the assemblies to be physically available at all times.

Upvotes: 2

Related Questions