是否有更好的(性能更高或更漂亮的代码;)方法来查找类型的所有派生类型? 目前我正在使用类似的东西:
我想知道是否有更好的方法来做到这一点?
我once使用这个Linq方法来获取从基类型B继承的所有类型:
var listOfBs = (
from domainAssembly in AppDomain.CurrentDomain.GetAssemblies()
// alternative: from domainAssembly in domainAssembly.GetExportedTypes()
from type in domainAssembly.GetTypes()
where typeof(B).IsAssignableFrom(type)
// alternative: && type != typeof(B)
// alternative: && ! type.IsAbstract
// alternative: where type.IsSubclassOf(typeof(B))
select type).ToArray();
编辑:由于这似乎仍然得到更多的代表(因此更多的视图),让我添加一个流畅的版本和更多细节:
var listOfBs = AppDomain.CurrentDomain.GetAssemblies()
// alternative: .GetExportedTypes()
.SelectMany(domainAssembly => domainAssembly.GetTypes())
.Where(type => typeof(B).IsAssignableFrom(type)
// alternative: => type.IsSubclassOf(typeof(B))
// alternative: && type != typeof(B)
// alternative: && ! type.IsAbstract
).ToArray();
详情:
Lazy
,可能会提高效率。domainAssembly.GetExportedTypes()
(微)优化它
仅检索公开可见的类型(如果这就是您所需要的)。Type.IsAssignable
也将获得原始(非派生)类型。 (Type.IsSubclassOf
不会,但如果基本类型是接口,Type.IsSubclassOf
将不起作用)。但当然,可以排除原始基类:&& type != typeof(B)
。&& ! assemblyType.IsAbstract
。 (请注意,所有接口都被认为是抽象的,请参阅MSDN。)唯一的建议是使用
Type.IsSubclassOf
方法而不是
Type.IsAssignable
来检查特定类型是否派生于另一个类型。尽管如此,也许您需要使用 Type.IsAssignable
(例如,它适用于接口)。Assembly.GetExportedTypes()
仅检索公开可见的类型(如果是这种情况)。除此之外,没有办法加快速度。 LINQ 可能有助于提高可读性,但不会提高性能。
您可以通过首先测试相关类型是否属于所需的“类”来进行一些短路,以避免不必要地调用
IsAssignableFrom
,根据 Reflector 的说法,这是相当昂贵的调用。也就是说,您仅搜索类,测试枚举或数组的“可分配性”是没有意义的。
如果你想检查 matchType 是否是从 baseType 表示的类派生的,我会使用
matchType.IsSubclassOf(baseType)
如果你想检查 matchType 是否实现了由 baseType 表示的接口,我会使用
matchType.GetInterface(baseType.ToString(), false) != null
当然,我会将 baseType.ToString() 存储为全局变量,这样我就不需要一直调用它。由于您可能需要在有很多类型的上下文中使用它,因此您还可以考虑使用 System.Threading.Tasks.Parallel.ForEach-Loop 来迭代所有类型...
更好:使用
IsSubclassOf
代替
IsAssignable
。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
),因此我也排除了派生抽象类。你想做什么?可能有更好(或至少更有效)的方法来实现它。
public static Dictionay<Type, Type[]> DerivedTypes { get;set; }
其中 Type 是您想要包含在搜索中的任何类型 Type[] 是派生类型的列表。 当应用程序启动时填充字典并在应用程序的整个生命周期中使用它。