Come si ottiene una raccolta di tutti i tipi che ereditano da un altro tipo specifico?
Come si ottiene una raccolta di tutti i tipi che ereditano da un altro tipo specifico?
Risposte:
Qualcosa di simile a:
public IEnumerable<Type> FindDerivedTypes(Assembly assembly, Type baseType)
{
return assembly.GetTypes().Where(t => baseType.IsAssignableFrom(t));
}
Se hai bisogno di gestire i generici, diventa un po 'più complicato (ad esempio, passare il List<>
tipo aperto ma aspettarti di recuperare un tipo che deriva da List<int>
). Altrimenti è semplice però :)
Se vuoi escludere il tipo stesso, puoi farlo abbastanza facilmente:
public IEnumerable<Type> FindDerivedTypes(Assembly assembly, Type baseType)
{
return assembly.GetTypes().Where(t => t != baseType &&
baseType.IsAssignableFrom(t));
}
Nota che questo ti permetterà anche di specificare un'interfaccia e trovare tutti i tipi che la implementano, invece di lavorare solo con le classi come Type.IsSubclassOf
fa.
IsAssignableFrom
dovrebbe funzionare anche. In particolare, la mia versione gestisce anche le interfacce. Hai testato il mio codice? In quale caso la mia risposta non riesce?
Il metodo seguente otterrà una raccolta di tipi che ereditano un tipo.
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
Se è necessario includere tipi che implementano un'interfaccia, vedere la risposta di @Jon Skeet.
Devi enumerare tutti i tipi e verificare per ognuno se eredita quello che stai cercando.
Un codice come quello in questa domanda potrebbe esserti utile.
Considera l'utilizzo di questo metodo (scritto per un 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();
}