Get all derived types of a type
Object-Oriented Design practice on Codemia
Turn requirements into classes, and defend the design, on the problems that come up in OOD rounds.
Introduction
Finding all types derived from a base class or implementing an interface is a common reflection task in C#. It shows up in plugin systems, dependency injection registration, serializers, and factories. The core operation is simple, but production-safe scanning needs to account for interfaces, abstract types, assembly boundaries, and partially loadable assemblies.
The Basic Reflection Pattern
The usual approach is:
- choose the assemblies to scan
- read their types
- filter with
IsAssignableFrom - exclude the base type itself and any abstract types if needed
This pattern works for both subclasses and interface implementations.
Why IsAssignableFrom Is Usually Right
For interface scanning and inheritance scanning in one method, IsAssignableFrom is the practical choice.
If you use IsSubclassOf, interfaces are excluded and some valid matches are missed.
So the common rule is:
- use
IsSubclassOfonly for strict class inheritance checks - use
IsAssignableFromwhen you want subclasses or interface implementations
Scanning the Current AppDomain
If you truly want every currently loaded assembly, scan the current AppDomain.
This is convenient, but it only finds assemblies that are already loaded. If a plugin assembly exists on disk and was never loaded, it will not appear here automatically.
Scanning Specific Assemblies Is Often Better
In real applications, scanning every loaded assembly can be slow and noisy. It is usually better to target the assemblies you own or the plugin assemblies you loaded intentionally.
This reduces surprises and improves startup time.
Direct Children Versus Any Descendant
Sometimes you want only immediate subclasses, not every descendant.
That is different from IsAssignableFrom, which includes grandchildren and deeper inheritance chains.
Generic Types Need Extra Care
Open generic definitions are a special case. Suppose you want all implementations of IHandler<T>. The type check may need to inspect each implemented interface and compare generic definitions.
This is a common pattern in DI auto-registration.
Cache Results When the Set Is Stable
Reflection scans are not free. If the application loads the same assemblies and asks the same question repeatedly, cache the result.
Caching is especially useful during startup or command dispatch registration.
Common Pitfalls
A common mistake is assuming AppDomain.CurrentDomain.GetAssemblies() includes assemblies that exist on disk but were never loaded. It does not.
Another mistake is calling Assembly.GetTypes() without handling ReflectionTypeLoadException. One problematic type can otherwise break the whole scan.
Developers also often forget to filter out abstract classes, which leads to runtime failures when they try to instantiate the results.
Summary
- Use reflection to scan selected assemblies and filter types.
- '
IsAssignableFromis usually the right predicate for subclasses and interface implementations.' - Handle
ReflectionTypeLoadExceptionso partial load failures do not abort the scan. - Filter abstract types if you need instantiable implementations only.
- Cache the results when the type set is stable and reused.
Related reading
- Get lengths of a list in a jinja2 template
- Get type of a generic parameter in Java with reflection
- GetProperties to return all properties for an interface inheritance hierarchy
- Getting Spring Application Context
- Get currently focused element/control in a WPF window
- Get DateTime as UTC with Dapper
- Good reasons to prohibit inheritance in Java?
- How can I add to List? extends Number data structures?

OOD Fundamentals
Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Object-Oriented Design practice on Codemia
Turn requirements into classes, and defend the design, on the problems that come up in OOD rounds.