Я ценю, что это очень старый вопрос, но я подумал, что добавлю еще один ответ для будущих пользователей, так как все ответы на сегодняшний день используют некоторую форму Assembly.GetTypes
.
Хотя GetTypes () действительно возвращает все типы, это не обязательно означает, что вы можете активировать их и, таким образом, потенциально можете выбросить 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.
Таким образом, чтобы безопасно квалифицировать набор результатов для загружаемых типов, в соответствии с этим Фил Хаакед статья Получить все типы в сборке и код Джона Скита вы бы вместо этого сделайте что-то вроде:
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();
}