Reputation: 27011
How to find a Derived Class of a Generic Base Class when you only know the type of the Generic Base Class?
I've tried with the below method but doesnt compile:
private Type FindRepositoryType(Type entityType)
{
var repoTypes = Assembly.GetExecutingAssembly().GetTypes()
.Where(t => t.BaseType != null
&& t.BaseType.IsGenericType
&& t.BaseType.GetGenericTypeDefinition() == typeof(BaseRepository<entityType>))
.ToList();
return null;
}
var repoType = FindRepositoryType(typeof(Product));
I'm hoping to find the ProductRepository type:
public class ProductRepository : BaseRepository<Product>
{
}
Upvotes: 2
Views: 168
Reputation: 5402
Replace your Where
clause with:
.Where(t => t.BaseType != null
&& t.BaseType.IsGenericType
&& t.BaseType.GetGenericTypeDefinition() == typeof (BaseRepository<>)
&& t.BaseType.GetGenericArguments().Single() == entityType)
Upvotes: 3
Reputation: 11855
A slightly shorter alternative to the other answers (which also doesn't rely on the .NET 4.5 GenericTypeArguments
property) could be:
// Create a type that represents `BaseRepository` with `entityType` as the generic parameter
var expectedType = typeof(BaseRepository<>).MakeGenericType(entityType);
// verify that it actually exists in the current assembly (will throw if it doesn't)
return Assembly.GetExecutingAssembly().GetTypes().Single(p => p.BaseType == expectedType);
Upvotes: 2
Reputation: 387507
You were not too far off.
GetGenericTypeDefinition
will return the generic type without any type parameters. In your case, this will be BaseRepository<>
(note the empty brackets). If you want to match the generic type arguments too, you will need to use GetGenericArguments
as well. So your check will be this:
t.BaseType.GetGenericTypeDefinition() == typeof(BaseRepository<>) &&
t.BaseType.GetGenericArguments()[0] == entityType
While GetGenericArguments()
returns an array of types, you can be sure that there will be one, as you just before ensured that the generic type definition is BaseRepository<>
which has exactly one type argument.
Finally, you also want to return the type you find, instead of null
:
private Type FindRepositoryType (Type entityType)
{
return Assembly.GetExecutingAssembly().GetTypes()
.Where(t => t.BaseType != null
&& t.BaseType.IsGenericType
&& t.BaseType.GetGenericTypeDefinition() == typeof(BaseRepository<>)
&& t.BaseType.GetGenericArguments()[0] == entityType)
.FirstOrDefault();
}
Upvotes: 1