How to prevent ReflectionTypeLoadException when calling Assembly.GetTypes()

M4N picture M4N · Oct 25, 2011 · Viewed 36.1k times · Source

I'm trying to scan an assembly for types implementing a specific interface using code similar to this:

public List<Type> FindTypesImplementing<T>(string assemblyPath)
{
    var matchingTypes = new List<Type>();
    var asm = Assembly.LoadFrom(assemblyPath);
    foreach (var t in asm.GetTypes())
    {
        if (typeof(T).IsAssignableFrom(t))
            matchingTypes.Add(t);
    }
    return matchingTypes;
}

My problem is, that I get a ReflectionTypeLoadException when calling asm.GetTypes() in some cases, e.g. if the assembly contains types referencing an assembly which is currently not available.

In my case, I'm not interested in the types which cause the problem. The types I'm searching for do not need the non-available assemblies.

The question is: is it possible to somehow skip/ignore the types which cause the exception but still process the other types contained in the assembly?

Answer

Jon Skeet picture Jon Skeet · Oct 25, 2011

One fairly nasty way would be:

Type[] types;
try
{
    types = asm.GetTypes();
}
catch (ReflectionTypeLoadException e)
{
    types = e.Types;
}
foreach (var t in types.Where(t => t != null))
{
    ...
}

It's definitely annoying to have to do this though. You could use an extension method to make it nicer in the "client" code:

public static IEnumerable<Type> GetLoadableTypes(this Assembly assembly)
{
    // TODO: Argument validation
    try
    {
        return assembly.GetTypes();
    }
    catch (ReflectionTypeLoadException e)
    {
        return e.Types.Where(t => t != null);
    }
}

You may well wish to move the return statement out of the catch block - I'm not terribly keen on it being there myself, but it probably is the shortest code...