Как получить коллекцию всех типов, наследуемых от определенного другого типа?
Как получить коллекцию всех типов, наследуемых от определенного другого типа?
Ответы:
Что-то типа:
public IEnumerable<Type> FindDerivedTypes(Assembly assembly, Type baseType)
{
return assembly.GetTypes().Where(t => baseType.IsAssignableFrom(t));
}
Если вам нужно обрабатывать дженерики, это становится несколько сложнее (например, передача открытого List<>
типа, но ожидание возврата типа, производного от List<int>
). В остальном все просто :)
Если вы хотите исключить сам тип, вы можете сделать это достаточно легко:
public IEnumerable<Type> FindDerivedTypes(Assembly assembly, Type baseType)
{
return assembly.GetTypes().Where(t => t != baseType &&
baseType.IsAssignableFrom(t));
}
Обратите внимание, что это также позволит вам указать интерфейс и найти все типы, которые его реализуют, а не просто работать с классами, как это Type.IsSubclassOf
делает.
IsAssignableFrom
тоже должно работать. В частности, моя версия тоже справляется с интерфейсами. Вы тестировали мой код? В каком случае я не могу ответить?
Следующий метод получит коллекцию типов, наследующих тип.
C #
public IEnumerable<Type> FindSubClassesOf<TBaseType>()
{
var baseType = typeof(TBaseType);
var assembly = baseType.Assembly;
return assembly.GetTypes().Where(t => t.IsSubclassOf(baseType));
}
VB.NET
Public Function FindSubClasses(Of TBaseType)() As IEnumerable(Of Type)
Dim baseType = GetType(TBaseType)
Dim assembly = baseType.Assembly
Return From t In assembly.GetTypes()
Where t.IsSubClassOf(baseType)
Select t
End Function
Если вам нужно включить типы, реализующие интерфейс, см. Ответ @Jon Skeet.
Вы должны перечислить все типы и проверить для каждого, наследует ли он тот, который вы ищете.
Некоторые коды, подобные приведенному в этом вопросе, могут быть вам полезны.
Рассмотрите возможность использования этого метода (написанного для PCL):
public IEnumerable<Type> FindDerivedTypes( Assembly assembly, Type baseType )
{
TypeInfo baseTypeInfo = baseType.GetTypeInfo();
bool isClass = baseTypeInfo.IsClass, isInterface = baseTypeInfo.IsInterface;
return
from type in assembly.DefinedTypes
where isClass ? type.IsSubclassOf( baseType ) :
isInterface ? type.ImplementedInterfaces.Contains( baseTypeInfo.AsType() ) : false
select type.AsType();
}