【问题标题】:Get all derived types of a type获取一个类型的所有派生类型
【发布时间】:2010-10-25 20:31:43
【问题描述】:

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

  1. 获取使用过的程序集中的所有类型
  2. 用所有这些类型检查我的类型是否为“IsAssignable”

我想知道是否有更好的方法来做到这一点?

【问题讨论】:

  • 哪里奇怪了?这不是经常需要的。
  • 我只是认为这是一个沉重的性能成本,因为“只知道哪些类型是从某种类型派生的”(我会删掉“奇怪的”;)
  • 你看过使用Enumerable.OfType吗?

标签: c# .net


【解决方案1】:

once 使用了这个 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();

编辑:由于这似乎仍然获得更多代表(因此更多视图),让我添加更多细节:

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

【讨论】:

  • 由于某种原因(我没有深入研究细节)domainAssembly.GetExportedTypes() 无法从动态程序集中调用。 (在我的例子中,我创建了一个使用 .GetDerivedTypes() 方法扩展 Type 类的类,并从 MVC 控制器操作中调用它。)
  • 我不得不切换检查以获取从基类型 B 派生的所有类型,所以:where assemblyType.IsSubclassOf(typeof(B))
【解决方案2】:

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

唯一的建议是使用Type.IsSubclassOf 方法而不是Type.IsAssignable 来检查特定类型是否派生自另一个。不过,您可能需要使用Type.IsAssignable 的原因(例如,它适用于接口)。

【讨论】:

  • 注意:如果“基类”实际上是一个接口,则 IsSubclassOf 不起作用,而 IsAssignableFrom 则起作用。
  • @Stefan:是的,我在回答中提到了这一点。这完全取决于提问者想要使用的确切上下文。
【解决方案3】:

如果是这种情况,您可以挤出的唯一优化是使用Assembly.GetExportedTypes() 仅检索公开可见的类型。除此之外,没有办法加快速度。 LINQ 可能有助于提高可读性,但不会提高性能。

您可以做一些短路以避免不必要的调用 IsAssignableFrom,根据 Reflector 的说法,这是相当昂贵的调用,方法是首先测试所讨论的类型是否是必需的“类”。也就是说,您只搜索类,测试枚举或数组的“可分配性”毫无意义。

【讨论】:

  • 使用GetExportedTypes() 时,您需要过滤掉IsDynamic 为真的程序集,否则会抛出NotSupportedException。我在启动 ASP.NET Core 应用程序时遇到了这个问题;不确定动态程序集是由 ANC 还是我引用的库创建的。
【解决方案4】:

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

更好:使用IsSubclassOf 而不是IsAssignable

【讨论】:

  • 是什么让你说 IsSubclassOf “更好”?它不适用于接口,我看不到任何直接的好处......
  • 子类化隐含子类型化。子类型暗示可分配性。例如,I 和 I 没有子类或子类型关系,但如果 I 在 T 中是协变或逆变的,则其中一个可以分配给另一个。在考虑子类型问题时,IsSubClassOf 没有误报但有误报,IsAssignable 没有误报,但确实有误报。显然两者都不正确,所以哪个“更好”是一个判断电话;你更喜欢假阴性还是假阳性?
【解决方案5】:

假设 baseType 包含您要检查的 System.Type 对象,并且 matchType 包含具有当前迭代类型的 System.Type 对象(通过 foreach 循环或其他方式):

如果您想检查 matchType 是否派生自 baseType 表示的类,我会使用

matchType.IsSubclassOf(baseType)

如果你想检查 matchType 是否实现了我会使用的 baseType 表示的接口

matchType.GetInterface(baseType.ToString(), false) != null

当然,我会将 baseType.ToString() 存储为全局变量,因此我不需要一直调用它。而且由于您可能需要在具有很多类型的上下文中使用它,因此您还可以考虑使用 System.Threading.Tasks.Parallel.ForEach-Loop 来遍历所有类型...

【讨论】:

    【解决方案6】:

    如果您只是对浏览感兴趣,那么 .NET Reflector 可以做到这一点。但是,这并不是真正可行的事情。您想要当前加载的程序集中的所有类型吗?执行程序集引用的程序集?有许多不同的方法可以获取类型列表,而编写可以解释(并提供选项)的东西将是一个相当大的成本,而收益却相对较低。

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

    【讨论】:

      【解决方案7】:

      我最终使用了最佳答案给出的代码。唯一的问题是我希望代码更具可读性,所以我写了基本相同的东西,但改为这样:

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

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

      【讨论】:

        【解决方案8】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-10-25
          • 2015-03-30
          • 2011-01-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-07-07
          相关资源
          最近更新 更多