Find Types in All Assemblies

58,803

Solution 1

There are two steps to achieve this:

  • The AppDomain.CurrentDomain.GetAssemblies() gives you all assemblies loaded in the current application domain.
  • The Assembly class provides a GetTypes() method to retrieve all types within that particular assembly.

Hence your code might look like this:

foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
{
    foreach (Type t in a.GetTypes())
    {
        // ... do something with 't' ...
    }
}

To look for specific types (e.g. implementing a given interface, inheriting from a common ancestor or whatever) you'll have to filter-out the results. In case you need to do that on multiple places in your application it's a good idea to build a helper class providing different options. For example, I've commonly applied namespace prefix filters, interface implementation filters, and inheritance filters.

For detailed documentation have a look into MSDN here and here.

Solution 2

LINQ solution with check to see if the assembly is dynamic:

/// <summary>
/// Looks in all loaded assemblies for the given type.
/// </summary>
/// <param name="fullName">
/// The full name of the type.
/// </param>
/// <returns>
/// The <see cref="Type"/> found; null if not found.
/// </returns>
private static Type FindType(string fullName)
{
    return
        AppDomain.CurrentDomain.GetAssemblies()
            .Where(a => !a.IsDynamic)
            .SelectMany(a => a.GetTypes())
            .FirstOrDefault(t => t.FullName.Equals(fullName));
}

Solution 3

Easy using Linq:

IEnumerable<Type> types =
            from a in AppDomain.CurrentDomain.GetAssemblies()
            from t in a.GetTypes()
            select t;

foreach(Type t in types)
{
    ...
}

Solution 4

Most commonly you're only interested in the assemblies that are visible from the outside. Therefor you need to call GetExportedTypes() But besides that a ReflectionTypeLoadException can be thrown. The following code takes care of these situations.

public static IEnumerable<Type> FindTypes(Func<Type, bool> predicate)
{
    if (predicate == null)
        throw new ArgumentNullException(nameof(predicate));

    foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
    {
        if (!assembly.IsDynamic)
        {
            Type[] exportedTypes = null;
            try
            {
                exportedTypes = assembly.GetExportedTypes();
            }
            catch (ReflectionTypeLoadException e)
            {
                exportedTypes = e.Types;
            }

            if (exportedTypes != null)
            {
                foreach (var type in exportedTypes)
                {
                    if (predicate(type))
                        yield return type;
                }
            }
        }
    }
}
Share:
58,803
Brian Mains
Author by

Brian Mains

Computer Aid Inc. Consultant, Microsoft MVP.

Updated on July 05, 2022

Comments

  • Brian Mains
    Brian Mains almost 2 years

    I need to look for specific types in all assemblies in a web site or windows app, is there an easy way to do this? Like how the controller factory for ASP.NET MVC looks across all assemblies for controllers.

    Thanks.

  • Niall Connaughton
    Niall Connaughton over 13 years
    Of course, if you were going to do some filtering on those types and assemblies, you'd use LINQ, right? ;)
  • Ondrej Tucny
    Ondrej Tucny over 13 years
    @Niall Connaughton That's a matter of personal preference.
  • James Gaunt
    James Gaunt over 13 years
    I've found situations when doing this causes an exception, turned out to be because my application was generating dynamic assemblies, just a gotcha to be aware of. You can identify the dynamic assemblies and skip them like this stackoverflow.com/questions/1423733/… - if it does cause a problem
  • CodesInChaos
    CodesInChaos over 13 years
    Note that assemblies are only loaded on demand, i.e. when they are used for the first time.
  • Rafael Herscovici
    Rafael Herscovici over 3 years
    Actually, I still get the could not load type exception with your code.