Getting all types that implement an interface
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-write:
foreach (Type t in this.GetType().Assembly.GetTypes())
if (t is IMyInterface)
; //do stuff
Solution 1:
Mine would be this in c# 3.0 :)
var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
Basically, the least amount of iterations will always be:
loop assemblies
loop types
see if implemented.
Solution 2:
This worked for me. It loops though the classes and checks to see if they are derrived from myInterface
foreach (Type mytype in System.Reflection.Assembly.GetExecutingAssembly().GetTypes()
.Where(mytype => mytype .GetInterfaces().Contains(typeof(myInterface)))) {
//do stuff
}
Solution 3:
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<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);
}
}
}
And then:
private IEnumerable<Type> GetTypesWithInterface(Assembly asm) {
var it = typeof (IMyInterface);
return asm.GetLoadableTypes().Where(it.IsAssignableFrom).ToList();
}