Я вдячний, що це дуже давнє запитання, але я подумав, що буду додати ще одну відповідь для майбутніх користувачів, оскільки всі відповіді на сьогоднішній день використовують певну форму Assembly.GetTypes.
Хоча GetTypes () дійсно повертає всі типи, це не обов'язково означає, що ви можете їх активувати і, таким чином, потенційно можете кинути a ReflectionTypeLoadException.
Класичний приклад не в змозі активувати тип буде , коли тип повернутих derivedз , baseале baseвизначається в різній комплектації від такого derived, складального , що викликає збірки не посилань.
Отже, скажімо, у нас є:
Class A // in AssemblyA
Class B : Class A, IMyInterface // in AssemblyB
Class C // in AssemblyC which references AssemblyB but not AssemblyA
Якщо в ClassCчому знаходиться, AssemblyCто робимо щось відповідно до прийнятої відповіді:
var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
Тоді він кине а ReflectionTypeLoadException.
Це відбувається тому , що без посилання AssemblyA на AssemblyCвас не буде в змозі:
var bType = typeof(ClassB);
var bClass = (ClassB)Activator.CreateInstance(bType);
Іншими словами, ClassBце не завантажимо, що є те, що виклик GetTypes перевіряє та накидає.
Отже, щоб безпечно кваліфікувати набір результатів для типів, що завантажуються, відповідно до цієї статті Phil Haacked Отримати всі типи в зборах та код Джона Скета, ви замість цього зробите щось на кшталт:
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);
}
}
}
І потім:
private IEnumerable<Type> GetTypesWithInterface(Assembly asm) {
var it = typeof (IMyInterface);
return asm.GetLoadableTypes().Where(it.IsAssignableFrom).ToList();
}