The Light
The Light

Reputation: 27011

How to find a Derived Class of a Generic Base Class when you only know the type of the Generic Base Class?

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

Answers (3)

decPL
decPL

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

goric
goric

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

poke
poke

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

Related Questions