Як отримати колекцію всіх типів, які успадковуються від конкретного іншого типу?
Відповіді:
Щось на зразок:
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();
}