Aprecio que esta es una pregunta muy antigua, pero pensé que agregaría otra respuesta para futuros usuarios, ya que todas las respuestas hasta la fecha usan alguna forma de Assembly.GetTypes.
Si bien GetTypes () realmente devolverá todos los tipos, no necesariamente significa que podría activarlos y, por lo tanto, podría arrojar a ReflectionTypeLoadException.
Un ejemplo clásico para no poder activar un tipo sería cuando el tipo devuelto es derivedde basepero basese define en un ensamblaje diferente del de derived, un ensamblaje al que el ensamblado que llama no hace referencia.
Entonces digamos que tenemos:
Class A // in AssemblyA
Class B : Class A, IMyInterface // in AssemblyB
Class C // in AssemblyC which references AssemblyB but not AssemblyA
Si en ClassCcuál está adentro AssemblyC, entonces hacemos algo según la respuesta aceptada:
var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
Entonces arrojará un ReflectionTypeLoadException.
Esto se debe a que sin una referencia a AssemblyA en AssemblyCque no sería capaz de:
var bType = typeof(ClassB);
var bClass = (ClassB)Activator.CreateInstance(bType);
En otras palabras, ClassBno se puede cargar, que es algo que la llamada a GetTypes comprueba y lanza.
Entonces, para calificar de forma segura el conjunto de resultados para los tipos cargables, según este artículo de Phil Haacked Obtener todos los tipos en un ensamblaje y el código Jon Skeet, en su lugar, haría algo como:
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);
}
}
}
Y entonces:
private IEnumerable<Type> GetTypesWithInterface(Assembly asm) {
var it = typeof (IMyInterface);
return asm.GetLoadableTypes().Where(it.IsAssignableFrom).ToList();
}