Получите все типы С#, которые сначала реализуют интерфейс, но не производные классы

связанный с Получение всех типов, реализующих интерфейс, мы можем легко получить все типы в сборке, которые реализуют определенный интерфейс.

Пример:

interface IFace
{
}

class Face : IFace
{
}

class TwoFace : Face
{
}

Для этой структуры мы найдем оба класса через отражение, т.е. все классы, которые также получены из первой реализации, используя

GetTypes().Where(
  type => type.GetInterfaces().Contains(typeof(IFace))
)

Итак, вопрос : как я могу ограничить результат базовым классом, который изначально реализует интерфейс?! В этом примере: подходит только тип класса Face.

Ответ 1

Во-первых, я бы использовал Type.IsAssignableFrom, а не GetInterfaces, но тогда все, что вам нужно сделать, это исключить типы, родительский тип которых уже находится в наборе:

var allClasses = types.Where(type => typeof(IFace).IsAssignableFrom(type))
                      .ToList(); // Or use a HashSet, for better Contains perf.
var firstImplementations = allClasses
      .Except(allClasses.Where(t => allClasses.Contains(t.BaseType)));

Или, как отмечено в комментариях, эквивалентно:

var firstImplementations = allClasses.Where(t => !allClasses.Contains(t.BaseType));

Обратите внимание, что это не возвращает класс, который выводится из класса, который реализует интерфейс, но восстанавливает его.