Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get all types implementing specific open generic type

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) {   ... } 
like image 697
Rookian Avatar asked Dec 27 '11 13:12

Rookian


People also ask

How do you find the type of generic type?

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.

What is an open generic type?

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.

What are generic types in C #?

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.

What is generic in runtime?

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.


2 Answers

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 {} 
like image 100
Nick VanderPyle Avatar answered Sep 19 '22 07:09

Nick VanderPyle


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";     } } 
like image 25
Stefano Spinucci Avatar answered Sep 19 '22 07:09

Stefano Spinucci