使用反射查找从泛型类继承的类

本文关键字:继承 泛型类 反射 查找 | 更新日期: 2023-09-27 17:56:32

我需要一种方法来过滤程序集以获取从泛型类继承的所有类。我找到了一些帖子,但它们最像如何检查继承(例如,如何在不实例化的情况下检查一个类是否继承了另一个类?和检查一个类是否派生自泛型类)。但是这些帖子对我没有帮助。

我所有的类都继承自一个特定的类,称为 BaseRepository<T> ,但有些类可以从 InterventionBaseRepository<T> 继承(它也继承自BaseRepository<T>)。我需要找到他们。这是我到目前为止的代码:

var q = from t in Assembly.GetExecutingAssembly().GetTypes()
        where t.IsClass && 
             (t.Namespace != null &&
              t.Namespace.StartsWith("AgroWeb.Core.Data.Repository"))
        select t;

因此,简而言之,上面的查询按命名空间获取我的所有类,我需要在其中找到从InterventionBaseRepository<T>继承的类。

必须找到的类的签名示例:

public class CityRepository : InterventionBaseRepository<City>, ICityRepository

InterventionBaseRepository宣言:

public class InterventionBaseRepository<T> : BaseRepository<T>
    where T : Entity

我尝试使用IsAssignableFrom(),如上面链接的那些帖子中所述,如下所示:

t.IsAssignableFrom(typeof(InterventionBaseRepository<Entity>))

使用反射查找从泛型类继承的类

这是因为您正在检查实体而不是城市。如果要使用协变泛型参数,请为 InterventionBaseRepository 指定一个接口,如下所示:

public interface IInterventionBaseRepository<out T> { }

然后让你的 InterventionBaseRepository 实现它。现在,"回购<城市">可以被视为"回购<实体">。

所以:

public class InterventionBaseRepository<T> : BaseRepository<T>, IInterventionBaseRepository<T>
where T : Entity
{
}

来自这篇文章:

            CityRepository value = new CityRepository();
            Type type = value.GetType();
            Type baseType = type.BaseType;
            if (baseType.IsGenericType)
            {
                Console.WriteLine(baseType.Name + " is generic type");
                Type itemType = baseType.GetGenericArguments()[0];
                Console.WriteLine("Generic argument: " + itemType.Name);
                Type genericType = baseType.GetGenericTypeDefinition();
                Console.WriteLine("Generic type: " + genericType.Name);
                Console.WriteLine("Generic base type: " + genericType.BaseType.Name);
            }
            if (type.IsAssignableToGenericType(typeof(BaseRepository<>)))
            {
                Console.WriteLine("IsAssignableToGenericType: BaseRepository<>");
            }
        if (type.IsAssignableToGenericType(typeof(InterventionBaseRepository<>)))
        {
            Console.WriteLine("IsAssignableToGenericType: InterventionBaseRepository<>");
        }

和:

public static class Utils 
{
    public static bool IsAssignableToGenericType(this Type givenType, Type genericType)
    {
        var interfaceTypes = givenType.GetInterfaces();
        foreach (var it in interfaceTypes)
        {
            if (it.IsGenericType && it.GetGenericTypeDefinition() == genericType)
                return true;
        }
        if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType)
            return true;
        Type baseType = givenType.BaseType;
        if (baseType == null) return false;
        return IsAssignableToGenericType(baseType, genericType);
    }
}

输出:

InterventionBaseRepository`1 is generic type
Generic argument: City
Generic type: InterventionBaseRepository`1
Generic base type: BaseRepository`1
IsAssignableToGenericType: BaseRepository<>
IsAssignableToGenericType: InterventionBaseRepository<>