Получение списка наследуемых типов не работает для всех типов
Я написал небольшой метод для перечисления унаследованных типов, но он не работает с 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
находится в другой сборке.