Get all types implementing specific open generic type
如何获取实现特定开放泛型类型的所有类型?
例如:
1 | public interface IUserRepository : IRepository<User> |
查找实现
1 2 3 4 | public static IEnumerable<Type> GetAllTypesImplementingOpenGenericType(Type openGenericType, Assembly assembly) { ... } |
这将返回继承泛型基类的所有类型。不是所有继承通用接口的类型。
1 2 3 4 5 6 |
这将返回所有类型,包括接口、抽象和继承链中具有打开的泛型类型的具体类型。
1 2 3 4 5 6 7 8 9 10 11 12 | 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; } |
在本例中,第二个方法将找到ConcreteUserRepo和IUserRepository:
1 2 3 4 5 6 7 8 9 10 11 | public interface ConcreteUserRepo : IUserRepository {} public interface IUserRepository : IRepository<User> {} public interface IRepository<User> {} public class User {} |
解决方案实现时不使用LINQ,搜索通用和非通用接口,将返回类型筛选到类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | 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);} // 1: Start2.MessageHandlerXY loadableTypes = GetClassesImplementingAnInterface(dc.GetType().Assembly, typeof(IHandleMessageG<>)).Item2; foreach (var item in loadableTypes) { Console.WriteLine("2:" + item); } // 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 | openGenericType.IsAssignableFrom(myType.GetGenericTypeDefinition()) |
或
4