Jak znaleźć wszystkie typy w zestawie, które dziedziczą z określonego typu C #


92

Jak uzyskać kolekcję wszystkich typów, które dziedziczą z określonego innego typu?

Odpowiedzi:


151

Coś jak:

public IEnumerable<Type> FindDerivedTypes(Assembly assembly, Type baseType)
{
    return assembly.GetTypes().Where(t => baseType.IsAssignableFrom(t));
}

Jeśli potrzebujesz obsługiwać List<>typy generyczne, staje się to nieco trudniejsze (np. Przekazanie typu otwartego, ale oczekiwanie na powrót typu, który pochodzi z List<int>). W przeciwnym razie jest to proste :)

Jeśli chcesz wykluczyć sam typ, możesz to łatwo zrobić:

public IEnumerable<Type> FindDerivedTypes(Assembly assembly, Type baseType)
{
    return assembly.GetTypes().Where(t => t != baseType && 
                                          baseType.IsAssignableFrom(t));
}

Zauważ, że pozwoli ci to również określić interfejs i znaleźć wszystkie typy, które go implementują, zamiast tylko pracować z klasami, jak to Type.IsSubclassOfma miejsce.


2
Dzięki! Skończyło się na tym, że dzięki - skończyło się na tym publicznym statycznym List <Type> GetAllSubclassesOf (Type baseType) {return Assembly.GetAssembly (baseType) .GetTypes (). Gdzie (type => type.IsSubclassOf (baseType)). Notować(); }
aceinthehole

@Downvoter tutaj. Mój komentarz zaginął. Jak wskazuje aceinthehole, odpowiedź jest nieprawidłowa. Dodałem poprawną odpowiedź, ponieważ przegapiłem komentarz asów, dopóki nie stwierdziłem, że kod nie działa. Wesołych Świąt.
Tim Murphy,

@Tim: To nie jest niepoprawne, jest trochę inne. IsAssignableFrompowinno również działać. W szczególności moja wersja radzi sobie również z interfejsami. Czy przetestowałeś mój kod? W jakim przypadku moja odpowiedź kończy się niepowodzeniem?
Jon Skeet,

1
@Jon. Całkiem słusznie, twoja metoda obsługuje interfejsy. Jestem programistą VB, dziedziczymy klasy i implementujemy interfejsy. Czy jest inaczej w C #? Pytam, ponieważ pytanie, jak wymagałem, chce typów, które dziedziczą typ, a nie implementują typ.
Tim Murphy,

2
@Tim: W C # używamy po prostu ":" dla obu ... ale generalnie uważałbym interfejsy za część hierarchii dziedziczenia typu.
Jon Skeet,

27

Poniższa metoda spowoduje pobranie kolekcji typów, które dziedziczą typ.

DO#

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

Jeśli potrzebujesz dołączyć typy, które implementują interfejs, zobacz odpowiedź @Jon Skeet.



1

Rozważ użycie tej metody (napisanej dla języka 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();
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.