如何获取实现特定开放泛型类型的所有类型?
例如:
public interface IUserRepository : IRepository<User>
查找所有实现IRepository<>
的类型。
public static IEnumerable<Type> GetAllTypesImplementingOpenGenericType(Type openGenericType, Assembly assembly)
{
...
}
如何获取实现特定开放泛型类型的所有类型?
例如:
public interface IUserRepository : IRepository<User>
查找所有实现IRepository<>
的类型。
public static IEnumerable<Type> GetAllTypesImplementingOpenGenericType(Type openGenericType, Assembly assembly)
{
...
}
这将返回所有继承泛型基类的类型,而不是继承泛型接口的类型。
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;
这将返回所有类型,包括接口、抽象类和具有开放泛型类型的继承链中的具体类型。
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:
public class ConcreteUserRepo : IUserRepository
{}
public interface IUserRepository : IRepository<User>
{}
public interface IRepository<User>
{}
public class User
{}
没有使用LINQ实现的解决方案,同时搜索泛型和非泛型接口,并过滤返回类型为类。
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
// https://dev59.com/pHVD5IYBdhLWcg3wTJrF#12602220
// http://haacked.com/archive/2012/07/23/get-all-types-in-an-assembly.aspx/
// https://dev59.com/gWsz5IYBdhLWcg3wcndb
// return all types implementing a generic interface
// http://stackoverflow.com/questions/33694960/find-all-types-implementing-a-certain-generic-interface-with-specific-t-type
// https://dev59.com/Wmoy5IYBdhLWcg3wScPb
// https://dev59.com/TXNA5IYBdhLWcg3wBpBm
// https://dev59.com/52025IYBdhLWcg3wtoM_
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";
}
}
assemblyToScan
从单个参数更改为参数数组params Assembly[] assemblies
。 - Soren您可以尝试
openGenericType.IsAssignableFrom(myType.GetGenericTypeDefinition())
或者
myType.GetInterfaces().Any(i => i.GetGenericTypeDefinition() = openGenericType)
您可以使用以下代码获取实现了 IRepository<>
接口的所有类型:
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);
}
}