简体   繁体   中英

Find classes which inherits from a generic class using reflection

I need a way to filter my assemblies to get all classes that inherits from a generic class. I have found some posts but they are most like how to check the inheritence(eg How to check if a class inherits another class without instantiating it? and Check if a class is derived from a generic class ). But these posts didn't helped me.

All my classes inherits from a specific one, called BaseRepository<T> , but some classes can inherit from InterventionBaseRepository<T> (which inherits from BaseRepository<T> as well). I need to find them. This is my code until now:

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

So, in short, the query above gets all my classes by namespace which I need to find among them those who inherits from InterventionBaseRepository<T> .

An example of a signature of a class which must be found:

public class CityRepository : InterventionBaseRepository<City>, ICityRepository

And the InterventionBaseRepository declaration:

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

I tried to use IsAssignableFrom() as said in those posts linked above in the query like this:

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

It's because you are checking against Entity and not City. If you want to use covariant generic arguments then specify an interface for InterventionBaseRepository like this:

public interface IInterventionBaseRepository<out T> { }

Then have your InterventionBaseRepository implement it. Now Repo< City > can be treated as Repo< Entity >.

So:

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

from this post :

            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<>");
        }

and:

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);
    }
}

output:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM