Как найти все классы, которые реализуют общий абстрактный класс, используя отражение в C #? - PullRequest
0 голосов
/ 19 октября 2018

У меня есть c# класс, который выглядит следующим образом

public abstract class Listener<T> where T : Event
{
    public abstract void Handle(T _event);
}

Я расширяю этот класс примерно так

public class SendWelcomeEmail : Listener<UserWasCreated>
{
    public override void Handle(UserWasCreated _event)
    {
        //...
    }
}

Мне нужно использовать отражение, чтобы найти все классы, которые расширяютсяListener<> базовый класс.

Я попробовал следующее

var listeners = AppDomain.CurrentDomain.GetAssemblies()
                         .SelectMany(assembly => assembly.GetTypes())
                         .Where(x => x.IsClass && !x.IsInterface)
                         .Where(listener => !listener.IsAbstract && listener.IsGenericType && listener.GetGenericTypeDefinition() == typeof(Listener<>))
                         .ToList();

Но это ничего не возвращает.Это условие постоянно возвращает false listener.GetGenericTypeDefinition() == typeof(Listener<>)

Как правильно найти все классы, которые расширяют базовый класс Listener<>?

Ответы [ 2 ]

0 голосов
/ 19 октября 2018

Начните с создания необходимой инфраструктуры: добавьте больше инструментов в набор инструментов, а затем используйте эти инструменты.

Вы хотите перечислить все базовые типы типа, поэтому перечислите все базовые типы типа:

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;

Посмотрите, насколько проще читать запрос при создании инструментов, которые вам нужны по одному за раз?Что мы хотим знать? Если какой-либо базовый тип является слушателем .Итак, как читается код?«где тип, любой базовый тип - слушатель» - код читается как описание того, что он делает.

0 голосов
/ 19 октября 2018

Вы можете узнать, является ли любой базовый тип Listener<>, путем рекурсивной проверки является тип цели IsInheritedFrom it:

public static class Extension
{
    public static bool IsInheritedFrom(this Type type, Type Lookup)
    {
        var baseType = type.BaseType;
        if (baseType == null)
            return false;

        if (baseType.IsGenericType
                && baseType.GetGenericTypeDefinition() == Lookup)
            return true;

        return baseType.IsInheritedFrom(Lookup);
    }
}

var lookup = typeof(Listener<>);
var listeners = AppDomain.CurrentDomain.GetAssemblies()
    .SelectMany(assembly => assembly.GetTypes())
    .Where(x => x.IsClass && !x.IsAbstract && x.IsInheritedFrom(lookup))
    .ToList();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...