Найти все производные типы универсального класса - PullRequest
20 голосов
/ 12 августа 2011

У меня есть универсальный класс и производный класс, как показано ниже.

public class GenericClass<T> { ... }

public class DerivedClass : GenericClass<SomeType> { ... }

Как найти производный класс с помощью отражения? Я попробовал оба способа ниже, но, похоже, не работает.

System.Reflection.Assembly.GetExecutingAssembly().GetTypes().Where(t => typeof(GenericClass<>).IsAssignableFrom(t));

System.Reflection.Assembly.GetExecutingAssembly().GetTypes().Where(t => t.IsSubclassOf(typeof(GenericClass<>));

Ответы [ 3 ]

39 голосов
/ 12 августа 2011
var result = System.Reflection.Assembly.GetExecutingAssembly()
    .GetTypes()
    .Where(t => t.BaseType != null && t.BaseType.IsGenericType && 
                t.BaseType.GetGenericTypeDefinition() == typeof(GenericClass<>));
8 голосов
/ 08 июня 2012

Это немного сложнее, чем это.t.BaseType может возвращать ноль (например, когда t является интерфейсом).Также обратите внимание, что метод Type.IsSubclassOf не работает для универсальных типов!Если вы имеете дело с универсальным типом, вы должны использовать метод GetTypeDefinition.Недавно я писал в блоге о , как получить все производные типы класса .Вот метод IsSubclass, который работает и для обобщений:

public static bool IsSubclassOf(Type type, Type baseType)
{
    if (type == null || baseType == null || type == baseType)
        return false;

    if (baseType.IsGenericType == false)
    {
        if (type.IsGenericType == false)
            return type.IsSubclassOf(baseType);
    }
    else
    {
        baseType = baseType.GetGenericTypeDefinition();
    }

    type = type.BaseType;
    Type objectType = typeof(object);
    while (type != objectType && type != null)
    {
        Type curentType = type.IsGenericType ?
            type.GetGenericTypeDefinition() : type;
        if (curentType == baseType)
            return true;

        type = type.BaseType;
     }

    return false;
}
1 голос
/ 10 июля 2014

Поскольку мне нужно было рекурсивно найти все производные типы, я написал этот код и сообщу всем, кому он может понадобиться:

    public void ListAllDerviedTypes()
    {
        Type entityType = typeof(TableAdapter);
        Assembly assembly = Assembly.LoadFrom(entityType.Assembly.Location);
        Type[] types = assembly.GetTypes();

        List<Type> results = new List<Type>();
        GetAllDerivedTypesRecursively(types, typeof(SiteAndSectorsTable<>), ref results);

        foreach (var type in results)
        {
            Console.WriteLine(type.Name);
        }
    }

    private static void GetAllDerivedTypesRecursively(Type[] types, Type type1, ref List<Type> results)
    {
        if (type1.IsGenericType)
        {
            GetDerivedFromGeneric(types, type1, ref results);
        }
        else
        {
            GetDerivedFromNonGeneric(types, type1, ref results);
        }
    }

    private static void GetDerivedFromGeneric(Type[] types, Type type, ref List<Type> results)
    {
        var derivedTypes = types
            .Where(t => t.BaseType != null && t.BaseType.IsGenericType &&
                        t.BaseType.GetGenericTypeDefinition() == type).ToList();
        results.AddRange(derivedTypes);
        foreach (Type derivedType in derivedTypes)
        {
            GetAllDerivedTypesRecursively(types, derivedType, ref results);
        }
    }


    public static void GetDerivedFromNonGeneric(Type[] types, Type type, ref List<Type> results)
    {
        var derivedTypes = types.Where(t => t != type && type.IsAssignableFrom(t)).ToList();

        results.AddRange(derivedTypes);
        foreach (Type derivedType in derivedTypes)
        {
            GetAllDerivedTypesRecursively(types, derivedType, ref results);
        }
    } 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...