Reputation: 2985
I have a generic class and a derived class as following.
public class GenericClass<T> { ... }
public class DerivedClass : GenericClass<SomeType> { ... }
How do I find the derived class via reflection? I have tried both ways below, but doesn't seem to work.
System.Reflection.Assembly.GetExecutingAssembly().GetTypes().Where(t => typeof(GenericClass<>).IsAssignableFrom(t));
System.Reflection.Assembly.GetExecutingAssembly().GetTypes().Where(t => t.IsSubclassOf(typeof(GenericClass<>));
Upvotes: 25
Views: 10267
Reputation: 4837
It's a bit more complex than that. t.BaseType may return null (e.g. when t is an interface). Also note that the Type.IsSubclassOf method does not work for generic types! If you are dealing with a generic type you should use the GetTypeDefinition method. I recently blogged about how to get all derived types of a class. Here's an IsSubclass method that works for generics, too:
public static bool IsSubclassOf(Type type, Type baseType)
{
if (type == null || baseType == null || type == baseType)
return false;
if (baseType.IsGenericType == false)
{
if (type.IsGenericType == false)
return type.IsSubclassOf(baseType);
}
else
{
baseType = baseType.GetGenericTypeDefinition();
}
type = type.BaseType;
Type objectType = typeof(object);
while (type != objectType && type != null)
{
Type currentType = type.IsGenericType
? type.GetGenericTypeDefinition()
: type;
if (currentType == baseType)
return true;
type = type.BaseType;
}
return false;
}
Upvotes: 12
Reputation: 2385
An improved (shorter) version of Kim's answer:
public List<Type> GetAllDerivedTypes(Type baseType)
{
Assembly assembly = Assembly.LoadFrom(baseType.Assembly.Location);
Type[] typesInAssembly = assembly.GetTypes();
var results = new List<Type>();
GetAllDerivedTypesRecursively(typesInAssembly, baseType, ref results);
return results;
}
private static void GetAllDerivedTypesRecursively(Type[] types, Type baseType, ref List<Type> results)
{
Type[] derivedTypes;
if (baseType.IsGenericType)
derivedTypes = types.Where(t => t.BaseType != null && t.BaseType.IsGenericType && t.BaseType.GetGenericTypeDefinition() == baseType).ToArray();
else
derivedTypes = types.Where(t => t != baseType && baseType.IsAssignableFrom(t)).ToArray();
results.AddRange(derivedTypes);
foreach (Type derivedType in derivedTypes)
GetAllDerivedTypesRecursively(types, derivedType, ref results);
}
Upvotes: 0
Reputation: 1118
Because I needed to recursively find all derived types I wrote this code and will share with anyone who may need it:
public void ListAllDerviedTypes()
{
Type entityType = typeof(TableAdapter);
Assembly assembly = Assembly.LoadFrom(entityType.Assembly.Location);
Type[] types = assembly.GetTypes();
List<Type> results = new List<Type>();
GetAllDerivedTypesRecursively(types, typeof(SiteAndSectorsTable<>), ref results);
foreach (var type in results)
{
Console.WriteLine(type.Name);
}
}
private static void GetAllDerivedTypesRecursively(Type[] types, Type type1, ref List<Type> results)
{
if (type1.IsGenericType)
{
GetDerivedFromGeneric(types, type1, ref results);
}
else
{
GetDerivedFromNonGeneric(types, type1, ref results);
}
}
private static void GetDerivedFromGeneric(Type[] types, Type type, ref List<Type> results)
{
var derivedTypes = types
.Where(t => t.BaseType != null && t.BaseType.IsGenericType &&
t.BaseType.GetGenericTypeDefinition() == type).ToList();
results.AddRange(derivedTypes);
foreach (Type derivedType in derivedTypes)
{
GetAllDerivedTypesRecursively(types, derivedType, ref results);
}
}
public static void GetDerivedFromNonGeneric(Type[] types, Type type, ref List<Type> results)
{
var derivedTypes = types.Where(t => t != type && type.IsAssignableFrom(t)).ToList();
results.AddRange(derivedTypes);
foreach (Type derivedType in derivedTypes)
{
GetAllDerivedTypesRecursively(types, derivedType, ref results);
}
}
Upvotes: 2
Reputation: 942247
var result = System.Reflection.Assembly.GetExecutingAssembly()
.GetTypes()
.Where(t => t.BaseType != null && t.BaseType.IsGenericType &&
t.BaseType.GetGenericTypeDefinition() == typeof(GenericClass<>));
Upvotes: 49