我很欣赏这是一个非常古老的问题,但我想我会为未来的用户添加另一个答案,因为迄今为止所有的答案都使用某种形式的 Assembly.GetTypes。
虽然 GetTypes() 确实会返回所有类型,但这并不一定意味着您可以激活它们,因此可能会抛出 ReflectionTypeLoadException。
无法激活类型的典型示例是,当返回的类型是来自base 的derived,但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。
这是因为如果在 AssemblyC 中没有对 AssemblyA 的引用,您将无法:
var bType = typeof(ClassB);
var bClass = (ClassB)Activator.CreateInstance(bType);
换句话说,ClassB 不是 可加载的,这是对 GetTypes 的调用检查并抛出的东西。
因此,为了安全地将结果集限定为可加载类型,那么根据这篇Phil Haacked 文章Get All Types in an Assembly 和Jon Skeet code,您将改为执行以下操作:
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();
}