Problem
How can I retrieve all types that implement an interface with the least amount of code and iterations using reflection in C# 3.0/.NET 3.5?
This is what I’d like to change:
foreach (Type t in this.GetType().Assembly.GetTypes())
if (t is IMyInterface)
; //do stuff
Asked by juan
Solution #1
In C# 3.0, mine would look like this:)
var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
Essentially, the smallest number of iterations is:
loop assemblies
loop types
see if implemented.
Answered by Darren Kopp
Solution #2
This was effective for me. It runs through the classes, looking for ones that derive from myInterface.
foreach (Type mytype in System.Reflection.Assembly.GetExecutingAssembly().GetTypes()
.Where(mytype => mytype .GetInterfaces().Contains(typeof(myInterface)))) {
//do stuff
}
Answered by Ben Watkins
Solution #3
I realize this is an old question, but I figured I’d offer another response for future users because all of the previous answers have used Assembly in some way. GetTypes.
While GetTypes() will yield all types, it does not guarantee that you can activate them, which could result in a ReflectionTypeLoadException.
When the type returned is derived from base, but base is specified in a different assembly than that of derived, an assembly that the calling assembly does not reference, the type cannot be activated.
Assume we have:
Class A // in AssemblyA
Class B : Class A, IMyInterface // in AssemblyB
Class C // in AssemblyC which references AssemblyB but not AssemblyA
If we perform something as per the accepted response in ClassC, which is in AssemblyC:
var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
Then a ReflectionTypeLoadException will be thrown.
This is because you wouldn’t be able to do the following without a reference to AssemblyA in AssemblyC:
var bType = typeof(ClassB);
var bClass = (ClassB)Activator.CreateInstance(bType);
In other words, ClassB is not loadable, which the GetTypes method detects and throws an exception for.
To safely qualify the result set for loadable types, you’d instead perform something like this, as per this Phil Haacked article Get All Types in an Assembly and 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);
}
}
}
And then:
private IEnumerable<Type> GetTypesWithInterface(Assembly asm) {
var it = typeof (IMyInterface);
return asm.GetLoadableTypes().Where(it.IsAssignableFrom).ToList();
}
Answered by rism
Solution #4
To locate all types in an assembly that implement the IFoo interface, use the following command:
var results = from type in someAssembly.GetTypes()
where typeof(IFoo).IsAssignableFrom(type)
select type;
It’s worth noting that Ryan Rinaldi’s recommendation was inaccurate. There will be no types returned. You are unable to write.
where type is IFoo
Type is a System, after all. There will never be an instance of type IFoo. Rather, you look to see if IFoo can be assigned from the type. As a result, you’ll obtain the results you’re looking for.
Also, for the same reason, Adam Wright’s option, which is now designated as the answer, is incorrect. Because all System.Type instances were not IFoo implementors, you’ll see 0 types returned at runtime.
Answered by Judah Gabriel Himango
Solution #5
IsAssignableFrom is used in other answers. FindInterfaces from the System namespace can likewise be used, as detailed here.
Here’s an example that looks for classes that implement a specific interface in all assemblies in the currently executing assembly’s folder (avoiding LINQ for clarity).
static void Main() {
const string qualifiedInterfaceName = "Interfaces.IMyInterface";
var interfaceFilter = new TypeFilter(InterfaceFilter);
var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var di = new DirectoryInfo(path);
foreach (var file in di.GetFiles("*.dll")) {
try {
var nextAssembly = Assembly.ReflectionOnlyLoadFrom(file.FullName);
foreach (var type in nextAssembly.GetTypes()) {
var myInterfaces = type.FindInterfaces(interfaceFilter, qualifiedInterfaceName);
if (myInterfaces.Length > 0) {
// This class implements the interface
}
}
} catch (BadImageFormatException) {
// Not a .net assembly - ignore
}
}
}
public static bool InterfaceFilter(Type typeObj, Object criteriaObj) {
return typeObj.ToString() == criteriaObj.ToString();
}
If you want to match many interfaces, you can create a list.
Answered by hillstuk
Post is based on https://stackoverflow.com/questions/26733/getting-all-types-that-implement-an-interface