Ich weiß, dass dies eine sehr alte Frage ist, aber ich dachte, ich würde eine weitere Antwort für zukünftige Benutzer hinzufügen, da alle bisherigen Antworten eine Form von Assembly.GetTypes
.
Obwohl GetTypes() tatsächlich alle Typen zurückgibt, bedeutet dies nicht unbedingt, dass Sie sie aktivieren können und somit möglicherweise ein ReflectionTypeLoadException
.
Ein klassisches Beispiel dafür, dass ein Typ nicht aktiviert werden kann, wäre, wenn der zurückgegebene Typ derived
von base
sondern base
in einer anderen Baugruppe definiert ist als die von derived
eine Assembly, die von der aufrufenden Assembly nicht referenziert wird.
Sagen wir, wir haben:
Class A // in AssemblyA
Class B : Class A, IMyInterface // in AssemblyB
Class C // in AssemblyC which references AssemblyB but not AssemblyA
Wenn in ClassC
die sich in AssemblyC
tun wir dann etwas gemäß der akzeptierten Antwort:
var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
Dann wird es eine ReflectionTypeLoadException
.
Denn ohne einen Verweis auf AssemblyA
in AssemblyC
wären Sie dazu nicht in der Lage:
var bType = typeof(ClassB);
var bClass = (ClassB)Activator.CreateInstance(bType);
Mit anderen Worten ClassB
ist nicht ladbar was der Aufruf von GetTypes prüft und auslöst.
Um also die Ergebnismenge für ladbare Typen sicher zu qualifizieren, muss man wie folgt vorgehen Phil Haacked Artikel Alle Typen in einer Baugruppe abrufen et Jon Skeet-Code würden Sie stattdessen etwas tun wie:
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);
}
}
}
Und dann:
private IEnumerable<Type> GetTypesWithInterface(Assembly asm) {
var it = typeof (IMyInterface);
return asm.GetLoadableTypes().Where(it.IsAssignableFrom).ToList();
}