Получение списка наследуемых типов не работает для всех типов

Я написал небольшой метод для перечисления унаследованных типов, но он не работает с TreeNode например:

Предположим, это классы:

class B { }
class A : B { }
class C :TreeNode { }

А потом:

GetInheritedTypes(typeof(A)); //typeof(B)
GetInheritedTypes(typeof(C)); // 0 items

Способ их перечисления:

List<Type> GetInheritedTypes(Type baseType) 
{ 
    return Assembly.GetAssembly(baseType)
                   .GetTypes()
                   .Where(type => type != baseType && type.IsAssignableFrom(baseType))
                   .ToList(); 
} 

Почему GetInheritedTypes(typeof(C)) возвращает 0 товаров вместо Typeof(TreeNode)?

2 ответа

Решение

Почему GetInheritedTypes(typeof(C)) возвращает 0 элементов вместо Typeof(TreeNode)?

Так как TreeNode не в той же сборке, что и C, Ваш запрос "из всех типов в той же сборке, что и C, дайте мне те, на которые назначается C".

Однако я подозреваю, что ваша настоящая проблема:

Как мне перечислить все базовые типы данного типа?

Вы не выполняете поиск по всем типам в сборке и проверяете, какие из них можно назначить. Это все равно что пытаться выяснить, кто твоя мама, спрашивая каждого человека в твоем городе "ты мама Джека?" вместо того, чтобы спрашивать Джека "кто твоя мама?"

Примерно так будет намного лучше

public static IEnumerable<Type> BaseTypes(this Type type)
{
    if (type == null) throw new ArgumentNullException("type");
    Type baseType = type;
    while(true)
    {
        baseType = baseType.BaseType;
        if (baseType == null) 
            break;
        yield return baseType;
    }
}

Комментатор спрашивает

Что делать, если вы хотите получить все реализованные интерфейсы?

Вызов GetInterfaces() на объекте типа.

(В более ранней версии этого поста предлагалось транзитивное закрытие интерфейсов; я забыл, что GetInterfaces уже делает это.)

Как еще был сломан мой оригинальный код?

Ну, предположим, например, у вас есть тип

class D<T> {}

и класс

class E : D<int> {}

Теперь вы спрашиваете "дано E, перечислите все типы X в сборке, так что значение типа E может быть назначен переменной типа X ". Что ж, D<T> находится в сборке; является D<T> такого типа? № Ан E присваивается переменной типа D<int>, не переменная типа D<T>,

Отношение "присваиваемое" и отношение "наследует от" имеют частичное совпадение, но они совсем не одно и то же, поэтому не притворяйтесь, что они есть.

Вы перечисляете только классы в той же сборке, что и Cи предположительно TreeNode находится в другой сборке.

Другие вопросы по тегам