Getting all types that implement an interface

前端 未结 17 1035
不思量自难忘°
不思量自难忘° 2020-11-22 00:34

Using reflection, how can I get all types that implement an interface with C# 3.0/.NET 3.5 with the least code, and minimizing iterations?

This is what I want to re-

17条回答
  •  太阳男子
    2020-11-22 01:39

    I appreciate this is a very old question but I thought I would add another answer for future users as all the answers to date use some form of Assembly.GetTypes.

    Whilst GetTypes() will indeed return all types, it does not necessarily mean you could activate them and could thus potentially throw a ReflectionTypeLoadException.

    A classic example for not being able to activate a type would be when the type returned is derived from base but base is defined in a different assembly from that of derived, an assembly that the calling assembly does not reference.

    So say we have:

    Class A // in AssemblyA
    Class B : Class A, IMyInterface // in AssemblyB
    Class C // in AssemblyC which references AssemblyB but not AssemblyA
    

    If in ClassC which is in AssemblyC we then do something as per accepted answer:

    var type = typeof(IMyInterface);
    var types = AppDomain.CurrentDomain.GetAssemblies()
        .SelectMany(s => s.GetTypes())
        .Where(p => type.IsAssignableFrom(p));
    

    Then it will throw a ReflectionTypeLoadException.

    This is because without a reference to AssemblyA in AssemblyC you would not be able to:

    var bType = typeof(ClassB);
    var bClass = (ClassB)Activator.CreateInstance(bType);
    

    In other words ClassB is not loadable which is something that the call to GetTypes checks and throws on.

    So to safely qualify the result set for loadable types then as per this Phil Haacked article Get All Types in an Assembly and Jon Skeet code you would instead do something like:

    public static class TypeLoaderExtensions {
        public static IEnumerable 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);
            }
        }
    }
    

    And then:

    private IEnumerable GetTypesWithInterface(Assembly asm) {
        var it = typeof (IMyInterface);
        return asm.GetLoadableTypes().Where(it.IsAssignableFrom).ToList();
    }
    

提交回复
热议问题