C# 获取一个类型的所有派生类型

C# 获取一个类型的所有派生类型,c#,.net,C#,.net,是否有更好的(性能更高或更好的代码;)方法来查找类型的所有派生类型? 目前,我正在使用类似于: 获取已用程序集中的所有类型 如果“可分配”,请将我的类型与所有这些类型一起检查 我想知道是否有更好的方法来实现这一点?唯一可以从中挤出的优化是使用Assembly.GetExportedTypes()仅检索公开可见的类型(如果是这种情况)。除此之外,没有办法加快速度。LINQ在可读性方面可能有所帮助,但在性能方面却没有帮助 根据Reflector的说法,通过首先测试所讨论的类型是否为所需的“类”,您可

是否有更好的(性能更高或更好的代码;)方法来查找类型的所有派生类型? 目前,我正在使用类似于:

  • 获取已用程序集中的所有类型
  • 如果“可分配”,请将我的类型与所有这些类型一起检查

  • 我想知道是否有更好的方法来实现这一点?

    唯一可以从中挤出的优化是使用
    Assembly.GetExportedTypes()
    仅检索公开可见的类型(如果是这种情况)。除此之外,没有办法加快速度。LINQ在可读性方面可能有所帮助,但在性能方面却没有帮助


    根据Reflector的说法,通过首先测试所讨论的类型是否为所需的“类”,您可以进行一些短路,以避免对
    IsAssignableFrom
    进行不必要的调用,这是一个非常昂贵的调用。也就是说,您只搜索类,没有必要测试枚举或数组的“可分配性”。

    我很确定您建议的方法将是查找所有派生类型的更简单方法。父类不存储关于它们的子类是什么的任何信息(如果存储了,那将是非常愚蠢的),这意味着在这里无法避免搜索所有类型


    唯一的建议是使用
    Type.IsSubclassOf
    方法,而不是
    Type.IsAssignable
    ,以检查特定类型是否派生自另一个类型。尽管如此,可能还是有原因需要使用
    Type.IsAssignable
    (例如,它与接口一起工作)。

    如果您只是对浏览感兴趣,那么.NET Reflector就可以这样做。然而,这并不是真正可行的。是否需要当前加载的程序集中的所有类型?执行程序集引用的程序集?有许多不同的方法可以获得类型列表,而编写能够说明(并提供选项)的内容将是一个成本相当大、收益相对较低的过程


    你想干什么?可能有更好(或至少更有效)的方法来完成它。

    我认为没有更好或更直接的方法


    更好的方法是:使用
    IsSubclassOf
    而不是
    IsAssignable

    Asuming baseType包含一个系统。要检查并匹配的Type对象包含一个System。使用当前迭代的类型键入对象(通过foreach循环或其他方式):

    如果要检查matchType是否派生自我将使用的baseType表示的类

    matchType.IsSubclassOf(baseType)
    
    如果您想检查matchType是否实现了我将使用的baseType表示的接口

    matchType.GetInterface(baseType.ToString(), false) != null
    
    当然,我会将baseType.ToString()存储为全局变量,这样就不必一直调用它。由于在很多类型的上下文中可能需要这个,所以您也可以考虑使用Sturth.thask.task.Realth.For循环来遍历所有类型…

    < P>我使用这个LINQ方法从基类B继承所有类型:

        var listOfBs = (
                        from domainAssembly in AppDomain.CurrentDomain.GetAssemblies()
                        // alternative: from domainAssembly in domainAssembly.GetExportedTypes()
                        from assemblyType in domainAssembly.GetTypes()
                        where typeof(B).IsAssignableFrom(assemblyType)
                        // alternative: where assemblyType.IsSubclassOf(typeof(B))
                        // alternative: && ! assemblyType.IsAbstract
                        select assemblyType).ToArray();
    
    编辑:由于这似乎仍能获得更多的代表性(从而获得更多的视图),让我添加一些详细信息:

    • 正如上面提到的链接状态一样,此方法在每个调用上使用反射。因此,当对同一类型重复使用该方法时, 只需加载一次,就可以使其更加高效
    • 正如所建议的,也许您可以使用
      domainAssembly.GetExportedTypes()
      只检索公开可见的类型(如果您只需要这些)
    • 如前所述,
      Type.IsAssignable
      还将获得原始(非派生)类型。(
      Type.IsSubclassOf
      将不起作用,但如果基本类型是接口,则
      Type.IsSubclassOf
      将不起作用)
    • 您可能想要/需要检查“真实”类:
      &!assemblyType.IsAbstract
      。(请注意,所有接口都被认为是抽象的,请参阅。)

    只需在开始时创建一个派生类型的静态字典,并使用它进行查找。 例如,
    publicstaticdictionayderivedtypes{get;set;}
    其中Type是要包含在搜索中的任何类型 类型[]是派生类型的列表。
    在应用程序启动时填写字典,并在应用程序的整个生命周期中使用它。

    我最终使用了上面答案给出的代码。唯一的问题是我想让代码更具可读性,所以我写了基本相同的东西,但却像这样:

    var derived_types = new List<Type>();
    foreach (var domain_assembly in AppDomain.CurrentDomain.GetAssemblies())
    {
      var assembly_types = domain_assembly.GetTypes()
        .Where(type => type.IsSubclassOf(typeof(MyType)) && !type.IsAbstract);
    
      derived_types.AddRange(assembly_types);
    }
    
    var派生的_类型=新列表();
    foreach(AppDomain.CurrentDomain.GetAssemblys()中的var-domain\u程序集)
    {
    var assembly\u types=domain\u assembly.GetTypes()
    其中(type=>type.IsSubclassOf(typeof(MyType))&&!type.IsAbstract);
    派生类型。AddRange(程序集类型);
    }
    

    在我的例子中,我使用了
    type.IsSubClassOf(MyType)
    ,因为我只需要派生类型,不包括上面提到的基类。我还需要派生类型不是抽象的(
    !type.isastract
    ),所以我也排除了派生的抽象类。

    这有什么奇怪的?这不是经常需要的东西。我只是认为这是一个沉重的性能成本,因为“仅仅知道哪些类型是从某个类型派生的”(我将删去“奇怪的”;),您有没有考虑过使用它?注意:如果“基类”“实际上是一个接口,而IsAssignableFrom是。”@Stefan:是的,我在回答中提到过。这完全取决于提问者想要使用的确切上下文。是什么让你说IsSubclassOf“更好”?它不适用于接口,我看不到任何直接的好处…子类化意味着子类型化。子类型意味着可分配性。例如,我和我没有子类或子类型关系,但如果我在T中是协变或逆变的,则一个可分配给另一个。考虑子类型问题时,IsSubClassOf没有误报但有误报,IsAssignable没有误报但有误报。显然两者都不是