Начните с создания необходимой инфраструктуры: добавьте больше инструментов в набор инструментов, а затем используйте эти инструменты.
Вы хотите перечислить все базовые типы типа, поэтому перечислите все базовые типы типа:
static class Extensions
{
public static IEnumerable<Type> BaseTypes(this Type type)
{
Type t = type;
while (true)
{
t = t.BaseType;
if (t == null) break;
yield return t;
}
}
}
Теперь у нас есть полезный инструмент в нашей панели инструментов.
У нас есть тип в руке.Мы хотим знать, верно ли что-либо для любого из его базовых типов.Поэтому мы должны использовать Any
:
static bool AnyBaseType(this Type type, Func<Type, bool> predicate) =>
type.BaseTypes().Any(predicate);
Теперь у нас есть еще один полезный инструмент.
Мы хотим знать, является ли конкретный тип конкретным универсальным:
static bool IsParticularGeneric(this Type type, Type generic) =>
type.IsGenericType && type.GetGenericTypeDefinition() == generic;
Мы хотим знать, является ли конкретный тип слушателем:
static bool IsListener(Type type) =>
type.IsParticularGeneric(typeof(Listener<>));
Теперьу нас есть инструменты, которые нам нужны.
var listeners = from assembly in AppDomain.CurrentDomain.GetAssemblies()
from type in assembly.GetTypes()
where type.AnyBaseType(IsListener)
select type;
Посмотрите, насколько проще читать запрос при создании инструментов, которые вам нужны по одному за раз?Что мы хотим знать? Если какой-либо базовый тип является слушателем .Итак, как читается код?«где тип, любой базовый тип - слушатель» - код читается как описание того, что он делает.