检查类型是否派生自抽象泛型类

时间:2014-04-03 15:58:17

标签: c# generics reflection

我需要获得从一些抽象泛型类派生的所有类型。我还需要获得泛型类型(如实现通用接口的类型上的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<>)));

3 个答案:

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

答案 1 :(得分:1)

您无法从未构造的泛型类型中寻找派生。您必须在Type.GetGenericTypeDefinition()上明确呼叫BaseType,以检查它是否等于typeof(AbstractValidator<>)

请注意,如果您使用标记界面(例如IAbstractValidator&#39;这是非通用的,可能会暴露非通用的包装方法供消费者使用,而这些方法并不知道确切的类型。如果你使用它,你可以使用IsAssignableFrom,尽管你必须小心不要让它倒退。您希望typeof(IAbstractValidator).IsAssignableFrom(type)获得正确的检查。这种特殊的方法很容易翻转,因为它看起来类似于if (x is type)

答案 2 :(得分: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