2

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(e.g. 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>))
Community
  • 1
  • 1
DontVoteMeDown
  • 21,122
  • 10
  • 69
  • 105

2 Answers2

0

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
{
}
James Lucas
  • 2,452
  • 10
  • 15
0

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<>
Community
  • 1
  • 1
Arie
  • 5,251
  • 2
  • 33
  • 54
  • Note that OP linked to very similar code and claim it did not work in they case... (http://stackoverflow.com/questions/457676/check-if-a-class-is-derived-from-a-generic-class) – Alexei Levenkov Jun 15 '15 at 15:22
  • @AlexeiLevenkov I checked my code and it works with mockup classes that represent the scenario given by the OP. It should work if he checks: var q = from t in Assembly.GetExecutingAssembly().GetTypes() where t.IsClass && (t.Namespace != null && t.Namespace.StartsWith("AgroWeb.Core.Data.Repository")) && t.IsAssignableToGenericType(typeof(InterventionBaseRepository<>)) select t; – Arie Jun 16 '15 at 06:02
  • Your code looks fine as there is really only one way to achieve what looks like goals of the question. The note is about OP already aware of the approach and somehow not not able to get it work to achieve actual, possibly slightly different goal. – Alexei Levenkov Jun 16 '15 at 17:03