Як знайти всі типи в збірці, яка успадковується від конкретного типу C #


92

Як отримати колекцію всіх типів, які успадковуються від конкретного іншого типу?

Відповіді:


150

Щось на зразок:

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це робить.


2
Дякую! У підсумку я використав цю подяку - я використав цей загальнодоступний статичний список <Type> GetAllSubclassesOf (Type baseType) {return Assembly.GetAssembly (baseType) .GetTypes (). Де (type => type.IsSubclassOf (baseType)). ToList (); }
aceinthehole

@Downvoter тут. Мій коментар зник. Як вказує ацетиновий отвір, відповідь неправильна. Я додав правильну відповідь, оскільки пропустив коментар тузів, поки не виявив, що код не працює. Щасливого Різдва.
Тім Мерфі

@Tim: Це не неправильно, воно дещо інше. IsAssignableFromтакож має працювати. Зокрема, моя версія також справляється з інтерфейсами. Ви перевірили мій код? У якому випадку моя відповідь не вдається?
Джон Скіт,

1
@Jon. Цілком правильно, ваш метод обробляє інтерфейси. Я програміст VB, ми успадковуємо класи та реалізуємо інтерфейси. Чи відрізняється це в C #? Я запитую, оскільки питання, як я вимагав, вимагає, щоб типи, які успадковують тип, не реалізовували тип.
Тім Мерфі

2
@Tim: У C # ми просто використовуємо ":" для обох ... але я, як правило, розглядаю інтерфейси як частину ієрархії успадкування типу.
Джон Скіт,

27

Наступний метод отримає колекцію типів, які успадковують тип.

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.


1

Ви повинні перерахувати всі типи та перевірити, чи кожен з них успадковує той, який ви шукаєте.

Деякий код, подібний коду в цьому питанні, може бути для вас корисним.


1

Подумайте про використання цього методу (написаного для 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();
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.