77

How do I get all types that implementing a specific open generic type?

For instance:

public interface IUserRepository : IRepository<User> 

Find all types that implement IRepository<>.

public static IEnumerable<Type> GetAllTypesImplementingOpenGenericType(Type openGenericType, Assembly assembly) { ... } 
0

4 Answers 4

105

This will return all types that inherit a generic base class. Not all types that inherit a generic interface.

var AllTypesOfIRepository = from x in Assembly.GetAssembly(typeof(AnyTypeInTargetAssembly)).GetTypes() let y = x.BaseType where !x.IsAbstract && !x.IsInterface && y != null && y.IsGenericType && y.GetGenericTypeDefinition() == typeof(IRepository<>) select x; 

This will return all types, including interfaces, abstracts, and concrete types that have the open generic type in its inheritance chain.

public static IEnumerable<Type> GetAllTypesImplementingOpenGenericType(Type openGenericType, Assembly assembly) { return from x in assembly.GetTypes() from z in x.GetInterfaces() let y = x.BaseType where (y != null && y.IsGenericType && openGenericType.IsAssignableFrom(y.GetGenericTypeDefinition())) || (z.IsGenericType && openGenericType.IsAssignableFrom(z.GetGenericTypeDefinition())) select x; } 

This second method will find ConcreteUserRepo and IUserRepository in this example:

public class ConcreteUserRepo : IUserRepository {} public interface IUserRepository : IRepository<User> {} public interface IRepository<User> {} public class User {} 
Sign up to request clarification or add additional context in comments.

5 Comments

Yes, but you will only get the concreterepo and irepo when it is in the same assembly. But this is absolutely ok.
Good catch! We'd have to be careful to load all the dependent assemblies, not just scan the currently loaded. Here's a SO about loading all assemblies: stackoverflow.com/questions/2384592/…
The typeof(IRepository<>) works only if the generic type has a single generic parameter. Any ideas for types that have more than one generic type parameter?
Sorry, I found the answer. All you have to do is typeof(IRepository<,>) (assuming two generic type parameters) and so on! Cool!
Won't this only work when the concrete type directly inherits the interface being searched for?
10

Solution implemented without LINQ, searching both generic and non generic interfaces, filtering the return type to classes.

public static class SampleCode { public static void Main() { IList<Type> loadableTypes; // instance the dummy class used to find the current assembly DummyClass dc = new DummyClass(); loadableTypes = GetClassesImplementingAnInterface(dc.GetType().Assembly, typeof(IMsgXX)).Item2; foreach (var item in loadableTypes) {Console.WriteLine("1: " + item);} // print // 1: Start2.MessageHandlerXY loadableTypes = GetClassesImplementingAnInterface(dc.GetType().Assembly, typeof(IHandleMessageG<>)).Item2; foreach (var item in loadableTypes) { Console.WriteLine("2: " + item); } // print // 2: Start2.MessageHandlerXY // 2: Start2.MessageHandlerZZ } ///<summary>Read all classes in an assembly that implement an interface (generic, or not generic)</summary> // // some references // return all types implementing an interface // http://stackoverflow.com/questions/26733/getting-all-types-that-implement-an-interface/12602220#12602220 // http://haacked.com/archive/2012/07/23/get-all-types-in-an-assembly.aspx/ // http://stackoverflow.com/questions/7889228/how-to-prevent-reflectiontypeloadexception-when-calling-assembly-gettypes // return all types implementing a generic interface // http://stackoverflow.com/questions/33694960/find-all-types-implementing-a-certain-generic-interface-with-specific-t-type // http://stackoverflow.com/questions/8645430/get-all-types-implementing-specific-open-generic-type // http://stackoverflow.com/questions/1121834/finding-out-if-a-type-implements-a-generic-interface // http://stackoverflow.com/questions/5849210/net-getting-all-implementations-of-a-generic-interface public static Tuple<bool, IList<Type>> GetClassesImplementingAnInterface(Assembly assemblyToScan, Type implementedInterface) { if (assemblyToScan == null) return Tuple.Create(false, (IList<Type>)null); if (implementedInterface == null || !implementedInterface.IsInterface) return Tuple.Create(false, (IList<Type>)null); IEnumerable<Type> typesInTheAssembly; try { typesInTheAssembly = assemblyToScan.GetTypes(); } catch (ReflectionTypeLoadException e) { typesInTheAssembly = e.Types.Where(t => t != null); } IList<Type> classesImplementingInterface = new List<Type>(); // if the interface is a generic interface if (implementedInterface.IsGenericType) { foreach (var typeInTheAssembly in typesInTheAssembly) { if (typeInTheAssembly.IsClass) { var typeInterfaces = typeInTheAssembly.GetInterfaces(); foreach (var typeInterface in typeInterfaces) { if (typeInterface.IsGenericType) { var typeGenericInterface = typeInterface.GetGenericTypeDefinition(); var implementedGenericInterface = implementedInterface.GetGenericTypeDefinition(); if (typeGenericInterface == implementedGenericInterface) { classesImplementingInterface.Add(typeInTheAssembly); } } } } } } else { foreach (var typeInTheAssembly in typesInTheAssembly) { if (typeInTheAssembly.IsClass) { // if the interface is a non-generic interface if (implementedInterface.IsAssignableFrom(typeInTheAssembly)) { classesImplementingInterface.Add(typeInTheAssembly); } } } } return Tuple.Create(true, classesImplementingInterface); } } public class DummyClass { } public interface IHandleMessageG<T> { } public interface IHandleMessage { } public interface IMsgXX { } public interface IMsgXY { } public interface IMsgZZ { } public class MessageHandlerXY : IHandleMessageG<IMsgXY>, IHandleMessage, IMsgXX { public string Handle(string a) { return "aaa"; } } public class MessageHandlerZZ : IHandleMessageG<IMsgZZ>, IHandleMessage { public string Handle(string a) { return "bbb"; } } 

1 Comment

awesome job. works in dotnet 2.2. just suggest changing assemblyToScan from single to an array of params params Assembly[] assemblies
7

You could try

openGenericType.IsAssignableFrom(myType.GetGenericTypeDefinition()) 

or

myType.GetInterfaces().Any(i => i.GetGenericTypeDefinition() = openGenericType) 

Comments

7

You can use the following code to get all types that implement IRepository<> interface:

List<Type> typesImplementingIRepository = new List<Type>(); IEnumerable<Type> allTypesInThisAssembly = Assembly.GetExecutingAssembly().GetTypes(); foreach (Type type in allTypesInThisAssembly) { if (type.GetInterface(typeof(IRepository<>).Name.ToString()) != null) { typesImplementingIRepository.Add(type); } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.