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