是否有更好的(更高性能或更好的代码;)查找类型的所有派生类型的方法? 目前我正在使用类似的东西:
我想知道这是否有更好的方法呢?
答案 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();
编辑:由于这似乎仍然有更多的代表(因此更多的观点),让我添加更多细节:
domainAssembly.GetExportedTypes()
进行(微观)优化
只检索公开可见的类型(如果这就是你需要的全部内容)。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
),所以我也要排除派生抽象类。