Rozumiem, że to bardzo stare pytanie, ale pomyślałem, że dodam kolejną odpowiedź dla przyszłych użytkowników, ponieważ wszystkie dotychczasowe odpowiedzi wykorzystują jakąś formę Assembly.GetTypes .
Chociaż GetTypes () rzeczywiście zwróci wszystkie typy, nie musi to oznaczać, że możesz je aktywować, a tym samym potencjalnie wyrzucić ReflectionTypeLoadException.
Klasycznym przykładem braku możliwości aktywacji typu jest sytuacja, gdy zwracany typ pochodzi derivedz zestawu, baseale basejest zdefiniowany w innym zestawie niż zestaw derived, do którego nie odwołuje się zestaw wywołujący.
Powiedzmy, że mamy:
Class A // in AssemblyA
Class B : Class A, IMyInterface // in AssemblyB
Class C // in AssemblyC which references AssemblyB but not AssemblyA
Jeśli w ClassCktórym jest AssemblyC, to robimy coś zgodnie z przyjętą odpowiedzią:
var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
Wtedy wyrzuci ReflectionTypeLoadException.
To dlatego, że bez odniesienia do AssemblyA w AssemblyCnie byłby w stanie:
var bType = typeof(ClassB);
var bClass = (ClassB)Activator.CreateInstance(bType);
Innymi słowy ClassBnie można go załadować co jest sprawdzane i uruchamiane przez wywołanie GetTypes.
Tak aby bezpiecznie zakwalifikować zestaw wyników dla ładowalnych typów wtedy jak na tym Phil Haacked artykule Get Wszystkie rodzaje w zespole i kod Jon Skeet byś zamiast zrobić coś takiego:
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);
}
}
}
I wtedy:
private IEnumerable<Type> GetTypesWithInterface(Assembly asm) {
var it = typeof (IMyInterface);
return asm.GetLoadableTypes().Where(it.IsAssignableFrom).ToList();
}