获取类型的所有派生类型

时间:2009-05-13 12:35:34

标签: c# .net

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

  1. 获取使用过的Assemblies中的所有类型
  2. 如果是'IsAssignable'
  3. ,请检查所有类型的类型

    我想知道这是否有更好的方法呢?

8 个答案:

答案 0 :(得分:61)

once使用此Linq方法获取从基类型B继承的所有类型:

    var listOfBs = (from domainAssembly in AppDomain.CurrentDomain.GetAssemblies()
                    from assemblyType in domainAssembly.GetTypes()
                    where typeof(B).IsAssignableFrom(assemblyType)
                    select assemblyType).ToArray();

编辑:由于这似乎仍然有更多的代表(因此更多的观点),让我添加更多细节:

  • 如上述链接所述,此方法在每次调用时都使用Reflection。因此,当重复使用相同类型的方法时, 通过加载一次,可能会提高效率。
  • 正如Anton所示,也许您可​​以使用domainAssembly.GetExportedTypes()进行(微观)优化 只检索公开可见的类型(如果这就是你需要的全部内容)。
  • Noldorin所述,Type.IsAssignable也会获得原始(非衍生)类型。 (Type.IsSubclassOf不会,但如果基本类型是接口,则Type.IsSubclassOf将无效。
  • 可能需要/需要检查“真正的”课程:&& ! assemblyType.IsAbstract。 (请注意,所有接口都被视为抽象,请参阅MSDN。)

答案 1 :(得分:10)

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

建议仅使用Type.IsSubclassOf方法而不是Type.IsAssignable来检查特定类型是否来自其他类型。不过,也许你需要使用Type.IsAssignable(例如,它适用于接口)。

答案 2 :(得分:7)

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

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

答案 3 :(得分:4)

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

更好:使用IsSubclassOf代替IsAssignable

答案 4 :(得分:4)

假设baseType包含要检查的System.Type对象,matchType包含一个System.Type对象,其中包含当前迭代的类型(通过foreach-loop或其他):

如果你想检查一下matchType是从baseType表示的类派生的,我会使用

matchType.IsSubclassOf(baseType)

如果你想检查wheather matchType实现baseType表示的接口,我会使用

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

当然我将baseType.ToString()存储为全局变量,所以我不需要一直调用它。既然你可能需要在有很多类型的环境中使用它,你也可以考虑使用System.Threading.Tasks.Parallel.ForEach-Loop遍历所有类型......

答案 5 :(得分:1)

如果您只是对浏览感兴趣,那么.NET Reflector可以执行此操作。但是,这不是真正可行的。您想要当前加载的程序集中的所有类型吗?执行程序集引用的程序集?有许多不同的方法可以获得类型列表,并且编写一些可以解释(并提供选项)的内容将是一个相当低的成本相当大的成本。

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

答案 6 :(得分:0)

只需在开始时创建派生类型的静态字典,然后进行查找。 例如。 {{1}} 其中“类型”是您要包括在搜索中的任何类型 Type []是派生类型的列表。 在应用启动时填满字典,并在应用的整个生命周期中使用它。

答案 7 :(得分:0)

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

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),所以我也要排除派生抽象类。