簡體   English   中英

如何使用C#中的反射查找實現泛型抽象類的所有類?

[英]How to find all classes that implements a generic abstract class using reflection in C#?

我有一個看起來像這樣的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<>基類的所有類?

首先構建您需要的基礎架構:在工具箱中放入更多工具,然后使用這些工具。

您想列出類型的所有基類型,因此列出類型的所有基類型:

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;

當您構建一次需要的工具時,查看查詢讀取的容易程度如何? 我們想知道什么? 如果任何基類型是監聽器 那么代碼如何讀取? “任何基類型都是監聽器的類型” - 代碼讀起來就像它的作用描述。

你可以找出任何基類型是一個Listener<> ,通過遞歸檢查是目標類型IsInheritedFrom它:

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();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM