Get All Types in an Assembly

asp.net mvc, code 0 comments suggest edit

Sometimes, you need to scan all the types in an assembly for a certain reason. For example, ASP.NET MVC does this to look for potential controllers.

One naïve implementation is to simply call Assembly.GetTypes() and hope for the best. But there’s a problem with this. As Suzanne Cook points out,

If a type can’t be loaded for some reason during a call to Module.GetTypes(), ReflectionTypeLoadException will be thrown. Assembly.GetTypes() also throws this because it calls Module.GetTypes().

In other words, if any type can’t be loaded, the entire method call blows up and you get zilch.

There’s multiple reason why a type can’t be loaded. Here’s one example:

public class Foo : Bar // Bar defined in another unavailable assembly
{
}

The class Foo derives from a class Bar, but Bar is defined in another assembly. Here’s a non-exhaustive list of reasons why loading Foo might fail:

  • The assembly containing Bar does not exist on disk.
  • The current user does not have permission to load the assembly containing Bar.
  • The assembly containing Bar is corrupted and not a valid assembly.

Once again, for more details check out Suzanne’s blog post on Debugging Assembly Loading Failures.

Solution

As you might expect, being able to get a list of types, even if you don’t plan on instantiating instances of them, is a common and important task. Fortunately, the ReflectionTypeLoadException thrown when a type can’t be loaded contains all the information you need. Here’s an example of ASP.NET MVC taking advantage of this within the internal TypeCacheUtil class (there’s a lot of other great code nuggets if you look around the source code)

Type[] typesInAsm;
try
{
    typesInAsm = assembly.GetTypes();
}
catch (ReflectionTypeLoadException ex)
{
    typesInAsm = ex.Types;
}

This would be more useful as a generic extension method. Well the estimable Jon Skeet has you covered in this StackOverflow answer (slightly edited to add in parameter validation):

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);
    }
}

I’ve found this code to be extremely useful many times.

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.

Comments

avatar

10 responses

  1. Avatar for Mark
    Mark July 23rd, 2012

    I am a simple enterprise .NET slave. I do datasets. I *never* have to scan for types in any assembly.

  2. Avatar for Luke McGregor
    Luke McGregor July 23rd, 2012

    Love it, I do this kinda thing quite a bit but I normally just ignore the assembly on a typeloadexception. This looks much tidier.

  3. Avatar for Luke Usher
    Luke Usher July 23rd, 2012

    What would also be use full is some better exception messages in the reflection API.
    Eg "the assembly could not be loaded because its missing a dependency". Great, which dependency?

  4. Avatar for Jason Wyglendowski
    Jason Wyglendowski July 23rd, 2012

    You could do the same thing with mono's version of reflector. But if you use the prescribe technique doesn't the assembly get loaded regardless if you want it or not?

  5. Avatar for Niklas
    Niklas July 31st, 2012

    Mark, that is so very sad. Have you considered a career change? Not that listing types makes life interesting, but not having to solve interesting problems will kill your brain in the long run.

  6. Avatar for joey
    joey January 15th, 2013

    it is some better exception messages in the reflection API.
    LF353

  7. Avatar for asdf
    asdf February 6th, 2015

    How do you implement the factory method?

  8. Avatar for Phrasenschwein
    Phrasenschwein February 17th, 2015

    FYI; if you want to get the current assembly to test above code use: Assembly.GetExecutingAssembly()

  9. Avatar for Stian
    Stian August 6th, 2015

    Is there any possibility to use this technique on a .Net 3.5 compact framework on a Pocket PC. I cant seem to find the referenced exception. All I get is a TypeLoadException.

  10. Avatar for Sipke Schoorstra
    Sipke Schoorstra December 19th, 2016

    Interestingly enough, Autofac comes with an extension method that has the exact same name.