Как найти все типы в сборке, которые наследуются от определенного типа C #

93

Как получить коллекцию всех типов, наследуемых от определенного другого типа?

козырь в кармане
источник

Ответы:

152

Что-то типа:

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
Благодарность! В итоге я использовал это Спасибо - я использовал этот общедоступный статический List <Type> GetAllSubclassesOf (Type baseType) {return Assembly.GetAssembly (baseType) .GetTypes (). Где (type => type.IsSubclassOf (baseType)). Составлять список(); }
aceinthehole
@Downvoter здесь. Мой комментарий пропал. Как указывает aceinthehole, ответ неверен. Я добавил правильный ответ, так как пропустил комментарий тузов, пока не обнаружил, что код не работает. С Рождеством.
Тим Мерфи
@ Тим: Это не неправильно, это немного другое. 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();
}
HappyNomad
источник