J'apprécie que c'est une très vieille question, mais j'ai pensé ajouter une autre réponse aux futurs utilisateurs car toutes les réponses à ce jour utilisent une forme de Assembly.GetTypes
.
Bien que GetTypes () renvoie en effet tous les types, cela ne signifie pas nécessairement que vous pouvez les activer et donc potentiellement lancer un ReflectionTypeLoadException
.
Un exemple classique pour ne pas pouvoir activer un type serait lorsque le type retourné est derived
de base
mais base
est défini dans un assembly différent de celui de derived
, un assembly que l'assembly appelant ne référence pas.
Alors disons que nous avons:
Class A // in AssemblyA
Class B : Class A, IMyInterface // in AssemblyB
Class C // in AssemblyC which references AssemblyB but not AssemblyA
Si dans ClassC
lequel se trouve AssemblyC
nous faisons alors quelque chose selon la réponse acceptée:
var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
Ensuite, il lancera un ReflectionTypeLoadException
.
En effet , sans référence à AssemblyA
en AssemblyC
vous ne seriez pas en mesure de:
var bType = typeof(ClassB);
var bClass = (ClassB)Activator.CreateInstance(bType);
En d'autres termes ClassB
n'est pas chargeable ce qui est quelque chose que l'appel à GetTypes vérifie et lance.
Donc, pour qualifier en toute sécurité l'ensemble de résultats pour les types chargeables, conformément à cet article de Phil Haacked Obtenir tous les types dans un code Assembly et Jon Skeet, vous devriez plutôt faire quelque chose comme:
public static class TypeLoaderExtensions {
public static IEnumerable<Type> GetLoadableTypes(this Assembly assembly) {
if (assembly == null) throw new ArgumentNullException("assembly");
try {
return assembly.GetTypes();
} catch (ReflectionTypeLoadException e) {
return e.Types.Where(t => t != null);
}
}
}
Et alors:
private IEnumerable<Type> GetTypesWithInterface(Assembly asm) {
var it = typeof (IMyInterface);
return asm.GetLoadableTypes().Where(it.IsAssignableFrom).ToList();
}