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) { ... }
Use the IsGenericType property to determine whether the type is generic, and use the IsGenericTypeDefinition property to determine whether the type is a generic type definition. Get an array that contains the generic type arguments, using the GetGenericArguments method.
An open generic type is simply a generic type whose type parameters have not been specified. For example, IEnumerable<> is an open generic type, and IEnumerable (or string or whatever) is a **closed generic type**, as its type parameter has been specified.
Generics allow you to define the specification of the data type of programming elements in a class or a method, until it is actually used in the program. In other words, generics allow you to write a class or method that can work with any data type.
When a generic type is first constructed with a value type as a parameter, the runtime creates a specialized generic type with the supplied parameter or parameters substituted in the appropriate locations in the MSIL. Specialized generic types are created one time for each unique value type that is used as a parameter.
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 {}
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"; } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With