Apprezzo che questa sia una domanda molto vecchia, ma ho pensato di aggiungere un'altra risposta per gli utenti futuri, dato che tutte le risposte fino ad oggi usano una qualche forma di Assembly.GetTypes
.
Mentre GetTypes () restituirà effettivamente tutti i tipi, ciò non significa necessariamente che potresti attivarli e quindi potenzialmente lanciare un ReflectionTypeLoadException
.
Un esempio classico per non poter attivare un tipo potrebbe essere quando il tipo restituito derived
proviene base
ma base
è definito in un assembly diverso da quello di derived
, un assembly a cui l'assembly chiamante non fa riferimento.
Quindi diciamo che abbiamo:
Class A // in AssemblyA
Class B : Class A, IMyInterface // in AssemblyB
Class C // in AssemblyC which references AssemblyB but not AssemblyA
Se in ClassC
quale è dentro AssemblyC
, facciamo qualcosa secondo la risposta accettata:
var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
Quindi lancerà a ReflectionTypeLoadException
.
Questo perché senza un riferimento a AssemblyA
in AssemblyC
te non sarebbe in grado di:
var bType = typeof(ClassB);
var bClass = (ClassB)Activator.CreateInstance(bType);
In altre parole, ClassB
non è caricabile, il che è qualcosa che la chiamata a GetTypes verifica e genera.
Quindi, per qualificare in modo sicuro il set di risultati per tipi caricabili, in base a questo articolo di Phil Haacked Ottieni tutti i tipi in un codice Assembly e Jon Skeet dovresti invece fare qualcosa del tipo:
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);
}
}
}
E poi:
private IEnumerable<Type> GetTypesWithInterface(Assembly asm) {
var it = typeof (IMyInterface);
return asm.GetLoadableTypes().Where(it.IsAssignableFrom).ToList();
}