2014-04-03 76 views
3

我需要获取从某个抽象泛型类派生的所有类型。我还需要获得泛型类型(如实现泛型接口的类型上的GetGenericArguments())。检查类型是否来自抽象泛型类

这是示例代码:

public abstract class AbstractValidator<T> 

public class CreateTripValidator : AbstractValidator<CreateTrip> 

public class CancelTripValidator : AbstractValidator<CancelTrip> 

我想要加载从AbstractValidator派生的所有类型。在这个例子中CreateTripValidator和CancelTripValidator。我希望每种类型的通用参数的检查类型。

我试图以这种方式,但他们没有工作:

var types = Assembly.GetExecutingAssembly().GetTypes().Where(
        t => t.IsSubclassOf(typeof(AbstractValidator<>))); 

var types = Assembly.GetExecutingAssembly().GetTypes().Where(
        t => t.IsAssignableFrom(typeof(AbstractValidator<>))); 
+1

是什么阻止您?你已经知道该怎么办了 – MikeSW

回答

1

你必须检查你自己的手中所有的基本类型:

private static bool IsSubclassOfRawGeneric(Type baseType, Type derivedType) { 
    while (derivedType != null && derivedType != typeof(object)) { 
     var currentType = derivedType.IsGenericType ? derivedType.GetGenericTypeDefinition() : derivedType; 
     if (baseType == currentType) { 
      return true; 
     } 

     derivedType = derivedType.BaseType; 
    } 
    return false; 
} 

然后你就可以使用它像这样:

var validatorType = typeof(AbstractValidator<>); 
    var subTypes = validatorType.Assembly 
     .GetTypes() 
     .Where(t => IsSubclassOfRawGeneric(validatorType, t)); 

Ideone:R7Q88Z

+0

请问这是因为:https://stackoverflow.com/a/457708 –

1

你不能找推导来自未构造的泛型类型。您必须在BaseType上明确呼叫Type.GetGenericTypeDefinition()以检查它是否等于typeof(AbstractValidator<>)

请注意,如果您使用诸如非通用的IAbstractValidator之类的标记接口,那么这种事情通常会更容易,可能会暴露非通用包装器方法以供不知道确切类型的消费者使用。如果你使用它,你可以使用IsAssignableFrom,尽管你必须小心不要让它倒退。您需要typeof(IAbstractValidator).IsAssignableFrom(type)才能获得正确的检查。这种特殊的方法很容易翻转,因为它似乎与if (x is type)类似。

3
static bool IsValidatorType(Type t) 
{ 
    while(t != null) 
    { 
     if(t.IsGenericType && t.GetGenericTypeDefinition == typeof(AbstractValidator<>)) 
     { 
      return true; 
     } 
     t = t.BaseClass; 
    } 
    return false; 
} 

var validatorTypes = Assembly.GetExecutingAssembly().GetTypes() 
    .Where(IsValidatorType); 
+0

请注意,在OP的情况下,他正在创建'AbstractValidator '的后代,所以你实际上需要检查每种类型的BaseType。 –

+0

@DanBryant - 它检查while循环中的每个基类型。 – Lee

+0

对不起,我错过了那个部分 –