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>))
答案 0 :(得分: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
{
}
答案 1 :(得分: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<>