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