By juan


2008-08-25 19:57:21 8 Comments

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

14 comments

@user6537157 2018-02-27 10:47:08

I got exceptions in the linq-code so I do it this way (without a complicated extension):

private static IList<Type> loadAllImplementingTypes(Type[] interfaces)
{
    IList<Type> implementingTypes = new List<Type>();

    // find all types
    foreach (var interfaceType in interfaces)
        foreach (var currentAsm in AppDomain.CurrentDomain.GetAssemblies())
            try
            {
                foreach (var currentType in currentAsm.GetTypes())
                    if (interfaceType.IsAssignableFrom(currentType) && currentType.IsClass && !currentType.IsAbstract)
                        implementingTypes.Add(currentType);
            }
            catch { }

    return implementingTypes;
}

@Jonathan Santiago 2019-08-05 13:26:03

   public IList<T> GetClassByType<T>()
   {
        return AppDomain.CurrentDomain.GetAssemblies()
                          .SelectMany(s => s.GetTypes())
                          .ToList(p => typeof(T)
                          .IsAssignableFrom(p) && !p.IsAbstract && !p.IsInterface)
                          .SelectList(c => (T)Activator.CreateInstance(c));
   }

@user489566 2019-01-21 20:23:17

Even better when choosing the Assembly location. Filter most of the assemblies if you know all your implemented interfaces are within the same Assembly.DefinedTypes.

// We get the assembly through the base class
var baseAssembly = typeof(baseClass).GetTypeInfo().Assembly;

// we filter the defined classes according to the interfaces they implement
var typeList = baseAssembly.DefinedTypes.Where(type => type.ImplementedInterfaces.Any(inter => inter == typeof(IMyInterface))).ToList();

By Can Bilgin

@Antonin GAVREL 2018-09-19 17:23:05

Other answer were not working with a generic interface.

This one does, just replace typeof(ISomeInterface) by typeof (T).

List<string> types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes())
            .Where(x => typeof(ISomeInterface).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract)
            .Select(x => x.Name).ToList();

So with

AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes())

we get all the assemblies

!x.IsInterface && !x.IsAbstract

is used to exclude the interface and abstract ones and

.Select(x => x.Name).ToList();

to have them in a list.

@Lukas Körfer 2018-09-19 21:57:05

Please explain how your solution works and why it is superior to all the other answers.

@Antonin GAVREL 2018-09-20 08:24:29

It is not superior or lower, the other answers didn't work for me and I bothered to share it.

@Lukas Körfer 2018-09-20 08:37:49

My comment was just about your answer being code-only, so I asked you to add some explanation.

@Antonin GAVREL 2018-09-20 08:48:39

yes no worries, I added it :) have a good day~

@Ben Watkins 2012-09-26 12:55:13

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
 }

@TamusJRoyce 2014-08-29 02:37:06

You are assuming the assembly is in the main executable. Not an additional project. You are also iterating unnecessarily though a bunch of iterations. It is better to have the framework do the heavy lifting. Then filter down farther when found. If relevant, please update your answer. Include List<T> reasoning. var classTypesImplementingInterface = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes()).Where(mytype => typeof(myInterface).IsAssignableFrom(mytype) && mytype.GetInterfaces().Contains(typeof(myInterface))); foreach(var item in items) Console.Log(item.Name);

@hillstuk 2012-06-08 11:18:55

Other answers here use IsAssignableFrom. You can also use FindInterfaces from the System namespace, as described here.

Here's an example that checks all assemblies in the currently executing assembly's folder, looking for classes that implement a certain interface (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();
}

You can set up a list of interfaces if you want to match more than one.

@senthil 2013-01-09 16:54:04

This one looks for string interface name which is what I was looking for.

@TamusJRoyce 2015-05-20 04:12:43

Works when loading an assembly in a different domain, as the type has to be serialized into a string. very awesome!

@bkwdesign 2019-10-03 17:06:46

I get: Cannot resolve dependency to assembly 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event.

@tags2k 2008-08-25 20:12:45

Edit: I've just seen the edit to clarify that the original question was for the reduction of iterations / code and that's all well and good as an exercise, but in real-world situations you're going to want the fastest implementation, regardless of how cool the underlying LINQ looks.

Here's my Utils method for iterating through the loaded types. It handles regular classes as well as interfaces, and the excludeSystemTypes option speeds things up hugely if you are looking for implementations in your own / third-party codebase.

public static List<Type> GetSubclassesOf(this Type type, bool excludeSystemTypes) {
    List<Type> list = new List<Type>();
    IEnumerator enumerator = Thread.GetDomain().GetAssemblies().GetEnumerator();
    while (enumerator.MoveNext()) {
        try {
            Type[] types = ((Assembly) enumerator.Current).GetTypes();
            if (!excludeSystemTypes || (excludeSystemTypes && !((Assembly) enumerator.Current).FullName.StartsWith("System."))) {
                IEnumerator enumerator2 = types.GetEnumerator();
                while (enumerator2.MoveNext()) {
                    Type current = (Type) enumerator2.Current;
                    if (type.IsInterface) {
                        if (current.GetInterface(type.FullName) != null) {
                            list.Add(current);
                        }
                    } else if (current.IsSubclassOf(type)) {
                        list.Add(current);
                    }
                }
            }
        } catch {
        }
    }
    return list;
}

It's not pretty, I'll admit.

@TamusJRoyce 2015-05-20 04:09:19

Enumerators implement IDisposable which isn't being disposed in a try/finally. It is better to use a foreach or linq.

@Lasse Vågsæther Karlsen 2008-08-25 20:05:21

loop through all loaded assemblies, loop through all their types, and check if they implement the interface.

something like:

Type ti = typeof(IYourInterface);
foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) {
    foreach (Type t in asm.GetTypes()) {
        if (ti.IsAssignableFrom(t)) {
            // here's your type in t
        }
    }
}

@rism 2015-03-31 22:41:52

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();
}

@Lari Tuomisto 2015-11-18 07:44:10

This helped me deal with a super weird problem, where in my test project GetTypes would fail and only in our CI-environment. GetLoadableTypes was a fix for this solution. The error wouldn't be reproducible in the local environment and it was this: System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information. More specifically it was complaining that there was a type that didn't have a concrete implementation and it happened in the unit test project. Thanks for this!

@Lightning3 2015-12-29 23:19:15

This answer should be marked as solution, it saved my ass today, because like @Lari Tuomisto said, on local env we couldn't re-product similar error

@Xavier Peña 2016-08-07 17:38:02

In case it helps someone else: this solution worked for me, but I had to modify it to remove the interface type from the list. I wanted to activate CreateInstance for all of them, and an exception was thrown when it was trying to create the actual interface (which had me confused for a while when I thought the actual interface was out of the way in this solution). So I changed the code to GetLoadableTypes(assembly).Where(interfaceType.IsAssignableF‌​rom).Where(t => !(t.Equals(interfaceType))).ToList();.

@Darren Kopp 2008-08-25 20:11:21

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.

@jtpereyda 2013-12-02 21:21:17

Note that the list may also include the interface itself. Change the last line to .Where(p => type.IsAssignableFrom(p) && !p.IsInterface); to filter it out (or p.IsClass).

@Sriram Sakthivel 2014-04-08 07:29:14

Note:This answer is wrong!, this checks "Assignment compatibility" not whether interface is implemented are not. For example List<string> doesn't implement IEnumerable<object> but this method will return true in .Net 4.0 due to covariance which is wrong indeed. Correct answer is here

@Darren Kopp 2014-04-08 13:45:02

@SriramSakthivel first off, generic values weren't specified. Second, this question pre-dates covariance. Third, you make the assumption that covariant return is not something they want.

@Sriram Sakthivel 2014-04-08 16:13:19

You're absolutely right darren, I know this is a old thread, I just registered my comment just for the future users to make aware of such problem exist. Not to offend you. and as question title says if OP is asking for Getting all types that implement an interface this code isn't doing that. but almost all the cases it works, no doubt. there are corner cases too as I said. Just to be aware of it;

@ErikE 2015-08-14 17:43:37

Also, there's no need to declare var type = typeof(IMyInterface) because typeof(IMyInterface) is evaluated at compile-time, and isn't re-evaluated over and over when in the Where statement.

@Jonesopolis 2015-12-23 18:11:37

Will also need to make sure the class isn't abstract => .Where(p => type.IsAssignableFrom(p) && p.IsClass && !p.IsAbstract

@Darren Kopp 2015-12-25 21:35:12

@Jonesopolis the asker didn't specify if they wanted to instantiate the class or not. abstract classes can still implement interfaces and may be what you want to look for depending on what you are doing.

@Jonesopolis 2015-12-26 13:46:24

@DarrenKopp good call. I had just made the assumption he was looking for instantiatable classes, I was when I found this question.

@Demodave 2016-04-21 13:21:22

make sure your assembly with the interface is included within the bin folder so that this code can pick it up, that was my problem

@Avi-B 2016-06-23 11:31:47

I tried it for the classes which implementing from the Interface. It works fine. But why doesn't it work for the abstract class?

@Hasan Bayat 2017-04-21 08:01:38

Add using: using System; and using System.Reflection and using System.Linq for beginners.

@snowflake 2018-04-21 09:31:32

@SriramSakthivel That sounds intesting, sadly googling for it I wasn't able to find anything. Can you tell me some keywords for the covariance thing so I can look it up?

@Sriram Sakthivel 2018-04-21 13:50:13

@snowflake Eric's article should help blogs.msdn.microsoft.com/ericlippert/2009/11/30/…. Google with keywords like "Eric lippert covariance" you will get lot of hits

@Carl Nayak 2010-11-12 14:30:46

This worked for me (if you wish you could exclude system types in the lookup):

Type lookupType = typeof (IMenuItem);
IEnumerable<Type> lookupTypes = GetType().Assembly.GetTypes().Where(
        t => lookupType.IsAssignableFrom(t) && !t.IsInterface); 

@Judah Gabriel Himango 2008-08-25 20:20:17

To find all types in an assembly that implement IFoo interface:

var results = from type in someAssembly.GetTypes()
              where typeof(IFoo).IsAssignableFrom(type)
              select type;

Note that Ryan Rinaldi's suggestion was incorrect. It will return 0 types. You cannot write

where type is IFoo

because type is a System.Type instance, and will never be of type IFoo. Instead, you check to see if IFoo is assignable from the type. That will get your expected results.

Also, Adam Wright's suggestion, which is currently marked as the answer, is incorrect as well, and for the same reason. At runtime, you'll see 0 types come back, because all System.Type instances weren't IFoo implementors.

@Ryan Rinaldi 2008-08-25 20:18:59

You could use some LINQ to get the list:

var types = from type in this.GetType().Assembly.GetTypes()
            where type is ISomeInterface
            select type;

But really, is that more readable?

@Joel Mueller 2009-05-29 20:22:05

It might be more readable, if it worked. Unfortunately, your where clause is checking to see if an instance of the System.Type class implements ISomeInterface, which will never be true, unless ISomeInterface is really IReflect or ICustomAttributeProvider, in which case it will always be true.

@TamusJRoyce 2015-05-20 04:06:54

Carl Nayak answer above has the answer to correcting the where clause: IsAssignableFrom. Easy mistake for an answer.

@Jorge Córdoba 2008-08-25 20:13:17

There's no easy way (in terms of performance) to do what you want to do.

Reflection works with assemblys and types mainly so you'll have to get all the types of the assembly and query them for the right interface. Here's an example:

Assembly asm = Assembly.Load("MyAssembly");
Type[] types = asm.GetTypes();
Type[] result = types.where(x => x.GetInterface("IMyInterface") != null);

That will get you all the types that implement the IMyInterface in the Assembly MyAssembly

Related Questions

Sponsored Content

26 Answered Questions

[SOLVED] Why not inherit from List<T>?

13 Answered Questions

[SOLVED] How to determine if a type implements an interface with C# reflection

20 Answered Questions

[SOLVED] LINQ's Distinct() on a particular property

35 Answered Questions

10 Answered Questions

[SOLVED] Interop type cannot be embedded

13 Answered Questions

19 Answered Questions

[SOLVED] Proper use of the IDisposable interface

17 Answered Questions

[SOLVED] Interface defining a constructor signature?

296 Answered Questions

[SOLVED] Hidden Features of C#?

  • 2008-08-12 16:32:24
  • Serhat Ozgel
  • 677352 View
  • 1475 Score
  • 296 Answer
  • Tags:   c# hidden-features

10 Answered Questions

Sponsored Content