BlackWaspTM
Reflection
.NET 1.1+

Identifying all Subclasses of a Class

In some situations it may be necessary to identify all of the subtypes of a given class that exist within an assembly. Subclasses cannot be read directly from a base class but can be easily determined using a simple query.

Reflecting Type Hierarchies

Sometimes you will find it necessary to find all of the types that exist within an assembly where the type is a subclass of another, specific class. For example, you may develop some software that uses late binding to implement a plug-in system. When an unknown assembly is provided, you might need to find all types that inherit from a known base type, as these would contain the plug-in features.

In the Reflection tutorial I described some ways to use reflection to determine type hierarchies. There is no single method that allows you to find all subtypes of a class, as this information is not stored within a type; this would be impossible as the subclasses may be developed completely separately. However, you can use several steps to find the appropriate types.

The steps are:

  1. Obtain a Type instance for the base class that forms the basis of the search.
  2. Get an array of the types in the target assembly.
  3. Loop through the types and use the provided type hierarchy reflection members to determine which of the types inherits from the target type and which do not.

To demonstrate, create a new console application and add the following classes. The first seven form a three-level inheritance hierarchy. The final two are not directly related to the previous seven. We will search these classes for those that are subclasses of Parent.

public class Parent { }
public class Child1 : Parent { }
public class Child2 : Parent { }
public class Grandchild11 : Child1 { }
public class Grandchild12 : Child1 { }
public class Grandchild21 : Child2 { }
public class Grandchild22 : Child2 { }
public class NotAChild { }
public class NotAGrandchild : NotAChild { }

For the first two steps of the process, we can use the typeof keyword to extract the type of the Parent class. To generate the array of types in the assembly we'll use the Assembly class's GetTypes method. We'll run this method against the executing assembly in this case. To do so, add the following two lines to the console application's Main method.

Type parentType = typeof(Parent);
Assembly assembly = Assembly.GetExecutingAssembly();
Type[] types = assembly.GetTypes();

With the necessary type references obtained, you can use IsSubclassOf against each element of the array to determine which types are subclasses of Parent. The sample code below uses a LINQ query for this purpose. However this could be substituted with a foreach loop.

IEnumerable<Type> subclasses = types.Where(t => t.IsSubclassOf(parentType));

foreach (Type type in subclasses)
{
    Console.WriteLine(type.Name);
}

/* OUTPUT

Child1
Child2
Grandchild11
Grandchild12
Grandchild21
Grandchild22

*/

Occasionally, you might only want to find the direct descendants of a type. In our example hierarchy, you might want to identify the child classes of Parent, but not the grandchildren. In these situations you can compare each type's BaseType property value to the desired type, as follows:

IEnumerable<Type> subclasses = types.Where(t => t.BaseType == parentType);

foreach (Type type in subclasses)
{
    Console.WriteLine(type.Name);
}

/* OUTPUT

Child1
Child2

*/
9 April 2014