Get all derived types of a type

I once used this Linq-method to get all types inheriting from a base type B:

    var listOfBs = (
                from domainAssembly in AppDomain.CurrentDomain.GetAssemblies()
                // alternative: from domainAssembly in domainAssembly.GetExportedTypes()
                from type in domainAssembly.GetTypes()
                where typeof(B).IsAssignableFrom(type)
                // alternative: && type != typeof(B)
                // alternative: && ! type.IsAbstract
                // alternative: where type.IsSubclassOf(typeof(B))
                select type).ToArray();

EDIT: As this still seems to get more rep (thus more views), let me add a fluent version and some more details:

   var listOfBs = AppDomain.CurrentDomain.GetAssemblies()
                // alternative: .GetExportedTypes()
                .SelectMany(domainAssembly => domainAssembly.GetTypes())
                .Where(type => typeof(B).IsAssignableFrom(type)
                // alternative: => type.IsSubclassOf(typeof(B))
                // alternative: && type != typeof(B)
                // alternative: && ! type.IsAbstract
                ).ToArray();

Details:

  • As the above-mentioned link states, this method uses Reflection on each call. So when using the method repeatedly for the same type,
    one could probably make it much more efficient by loading it once.
  • As Anton suggests, maybe you could (micro)optimize it using domainAssembly.GetExportedTypes()
    to retrieve only publicly visible types (if that’s all you need).
  • As Noldorin mentions, Type.IsAssignable will also get the original (non-derived) type. (Type.IsSubclassOf will not, but Type.IsSubclassOf will not work if the base type is an interface). But of course, one can exclude the original base class: && type != typeof(B).
  • One may want/need to check for a concrete implemented class, i.e. ignore abstract classes: && ! assemblyType.IsAbstract. (Note that all interfaces are considered abstract, see MSDN.)
  • FWIW: as Jon Skeet suggested in a similar question: “it is trickier if you need to handle generics”.
    A quick search returns some suggestions, but there are probably more, and I did not check them (e.g. for correctness):

Leave a Comment