Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用C#中的反射查找实现泛型抽象类的所有类?_C#_Linq_Reflection - Fatal编程技术网

如何使用C#中的反射查找实现泛型抽象类的所有类?

如何使用C#中的反射查找实现泛型抽象类的所有类?,c#,linq,reflection,C#,Linq,Reflection,我有一个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) {

我有一个
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)
    {
        //...
    }
}
公共抽象类侦听器,其中T:Event
{
公共摘要无效句柄(T_事件);
}
我把这个类扩展成这样

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)
    {
        //...
    }
}
public类SendWelcomeEmail:Listener
{
公共重写无效句柄(UserWasCreated\u事件)
{
//...
}
}
我需要使用反射来查找扩展
侦听器
基类的所有类

我尝试了以下方法

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();
var listeners=AppDomain.CurrentDomain.GetAssemblys()
.SelectMany(assembly=>assembly.GetTypes())
.Where(x=>x.IsClass&&!x.IsInterface)
.Where(listener=>!listener.isastract&&listener.IsGenericType&&listener.GetGenericTypeDefinition()==typeof(listener))
.ToList();
但这不会带来任何回报。此条件始终返回false
listener.GetGenericTypeDefinition()==typeof(listener)


如何正确查找扩展
侦听器
基类的所有类?

您可以通过递归检查is target type
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();
公共静态类扩展
{
公共静态bool为InheritedFrom(此类型,类型查找)
{
var baseType=type.baseType;
if(baseType==null)
返回false;
if(baseType.IsGenericType
&&baseType.GetGenericTypeDefinition()=查找)
返回true;
返回baseType.IsInheritedFrom(查找);
}
}
var lookup=typeof(侦听器);
var listeners=AppDomain.CurrentDomain.GetAssemblys()
.SelectMany(assembly=>assembly.GetTypes())
其中(x=>x.IsClass&!x.isastract&&x.IsInheritedFrom(查找))
.ToList();

从构建所需的基础设施开始:在工具箱中放入更多工具,然后使用这些工具

要列出类型的所有基类型,请列出类型的所有基类型:

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;
    }
}
}
现在我们有了另一个有用的工具

我们想知道特定类型是否为特定泛型:

static bool IsParticularGeneric(this Type type, Type generic) =>
  type.IsGenericType && type.GetGenericTypeDefinition() == generic;
我们想知道特定类型是否为侦听器:

static bool IsListener(Type type) =>
  type.IsParticularGeneric(typeof(Listener<>));

当您一次构建一个所需的工具时,查看查询的可读性有多容易?我们想知道什么如果任何基类型是侦听器。那么代码是如何读取的呢?“where type any base type is listener”--代码读起来像是对其功能的描述

你的问题毫无意义。您说您正在查找其基本类型包括
Listener
的类型,但您的查询查找的类型是
Listener
。如果您正在寻找基类型,那么在查询中的某个地方,您必须提到基类型!你需要后退一步,解决一个更容易的问题。假设我给你一个
类型
对象。你能列出它的所有基本类型吗?如果你不能做到这一点,那么你就不能解决更难的问题。当你陷入困境时,找到一个与你的问题相关的简单问题并解决它。你的查询在其他方面也很奇怪。比如,你说“类型是类而不是接口”。这就像说“我想要一只狗而不是章鱼”——当你知道它是一只狗的时候,你不必测试它的章鱼性。这段代码看起来像是在向编译器扔东西,希望有东西能坚持住。重新开始,仔细、逻辑地编写代码。另外,假设我们有一个扩展了SendWelcomeEmail的类
Foo
。它是否扩展了侦听器?当然有。但是你想把它列出来吗?或者您只想要直接扩展
Listener
的类型?@MikeA如果您只想知道从类继承的所有类,您可以在Visual Studio中将光标放在类名的某个位置并查找所有引用(按Ctrl+F12)谢谢您的帮助。只有在没有第三个+扩展名时,上述代码才起作用。意思是如果我有
Foo:SendWelcomeEmail
这个查询不会返回Foo,但会返回
SendWelcomeEmail