当您只知道通用基类的类型时,如何查找通用基类的派生类?

时间:2014-03-14 12:54:13

标签: c# .net generics reflection types

如果只知道通用基类的类型,如何查找通用基类的派生类?

我尝试使用以下方法,但没有编译:

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

我希望找到ProductRepository类型:

public class ProductRepository : BaseRepository<Product>
{

}

3 个答案:

答案 0 :(得分:3)

将您的Where子句替换为:

.Where(t => t.BaseType != null
         && t.BaseType.IsGenericType
         && t.BaseType.GetGenericTypeDefinition() == typeof (BaseRepository<>)
         && t.BaseType.GetGenericArguments().Single() == entityType)

答案 1 :(得分:2)

稍微更短的替代其他答案(也不依赖于.NET 4.5 GenericTypeArguments属性)可能是:

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

答案 2 :(得分:1)

你离我太远了。

GetGenericTypeDefinition将返回没有任何类型参数的泛型类型。在您的情况下,这将是BaseRepository<>(请注意空括号)。如果您也想匹配泛型类型参数,则还需要使用GetGenericArguments。所以你的支票就是这样:

t.BaseType.GetGenericTypeDefinition() == typeof(BaseRepository<>) && 
t.BaseType.GetGenericArguments()[0] == entityType

虽然GetGenericArguments()返回一个类型数组,但您可以确定会有一个类型,因为您刚才确保通用类型定义为BaseRepository<> 完全一种类型的论点。

最后,您还希望返回找到的类型,而不是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();
}