简体   繁体   中英

Check if type is derived from abstract generic class

I need to get all types that derive from some abstract generic class. I also need to get generic type (like GetGenericArguments() on type that implement generic interface).

This is sample code:

public abstract class AbstractValidator<T>

public class CreateTripValidator : AbstractValidator<CreateTrip>

public class CancelTripValidator : AbstractValidator<CancelTrip>

I want to load all types that derive from AbstractValidator. In this example CreateTripValidator and CancelTripValidator. And I want check type of generic argument for each of them.

I tried in this way but none of them works:

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

var types = Assembly.GetExecutingAssembly().GetTypes().Where(
                    t => t.IsAssignableFrom(typeof(AbstractValidator<>)));
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);

You must to check with your own hands all base types:

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

And then you can use it like this:

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

Ideone: R7Q88Z

You can't look for derivation from the unconstructed generic type. You'll have to explicitly call Type.GetGenericTypeDefinition() on the BaseType to check if it equals typeof(AbstractValidator<>) .

Note that this kind of thing is often easier if you use a marker interface like 'IAbstractValidator' which is non-generic, perhaps exposing non-generic wrapper methods for use by consumers that don't know the exact type. If you use that, you can make use of IsAssignableFrom, though you have to be careful not to get it backwards. You'll want typeof(IAbstractValidator).IsAssignableFrom(type) to get the correct check. This particular method is really easy to flip around because it seems analogous to if (x is type) .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM