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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/857705/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 04:27:18  来源:igfitidea点击:

Get all derived types of a type

c#.net

提问by Bluenuance

Is there a better (more performant or nicer code ;) way to find all derived Types of a Type? Currently im using something like:

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

  1. get all types in used Assemblies
  2. check my type with all those types if it is 'IsAssignable'
  1. 获取使用过的程序集中的所有类型
  2. 如果我的类型是“IsAssignable”,请检查所有这些类型

I was wondering if theres a better way todo this?

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

回答by Anton Gogolev

The only optimization you can squeeze out of this is to use Assembly.GetExportedTypes()to retrieve only publicly visible types if that's the case. Other than that, there's no way to speed things up. LINQ may help with readability side of things, but not performance-wise.

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

You can do some short-circuiting to avoid unnecessary calls to IsAssignableFromwhich is, according to Reflector, quite expensive one, by first testing whether the type in question is of required "class". That is, you're searching for classes only, there's no point in testing enums or arrays for "assignability".

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

回答by Noldorin

I'm pretty sure the method you suggested is going to be the easier way to find all derived types. Parent classes don't store any information about what their sub-classes are (it would be quite silly if they did), which means there's no avoiding a search through all the types here.

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

Only recommendation is to use the Type.IsSubclassOfmethod instead of Type.IsAssignablein order to check whether a particular type is derived from another. Still, perhaps there is a reason you need to use Type.IsAssignable(it works with interfaces, for example).

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

回答by Adam Robinson

If you're just interested in browsing, then .NET Reflector has the ability to do this. However, it isn't something that's really feasible. Would you want all types that are in the currently loaded assemblies? Assemblies referenced by the executing assembly? There are many different ways to obtain a list of Types, and writing something that would account for (and provide options for) would be a pretty big cost with relatively low benefit.

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

What are you trying to do? There's likely a better (or at least more efficient) way to accomplish it.

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

回答by Dario

I think there is no better or direct way.

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

Better: Use IsSubclassOfinstead of IsAssignable.

更好:使用IsSubclassOf代替IsAssignable

回答by Fredrik Rasch

Asuming baseType contains a System.Type object that you want to check against and matchType contains a System.Type object with the type of your current iteration (through a foreach-loop or whatever):

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

If you want to check wheather matchType is derived from the class represented by baseType I'd use

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

matchType.IsSubclassOf(baseType)

And if you want to check wheather matchType implements the interface represented by baseType I'd use

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

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

Of course I'd store baseType.ToString() as a global variable so I wouldn't need to call it all the time. And since you probably would need this in a context where you have a lot of types, you could also consider using the System.Threading.Tasks.Parallel.ForEach-Loop to iterate through all your types...

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

回答by Yahoo Serious

I onceused this Linq-method to get all types inheriting from a base type B:

曾经使用这个 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();

EDIT: As this still seems to get more rep (thus more views), let me add some more details:

编辑:由于这似乎仍然获得更多代表(因此更多的意见),让我添加一些更多的细节:

  • As the above-mentioned link states, this method uses Reflection on each call. So when using the method repeatedly for the same type, one could probably make it much more efficient by loading it once.
  • As Antonsuggests, maybe you could (micro)optimize it using domainAssembly.GetExportedTypes()to retrieve only publicly visible types (if that's all you need).
  • As Noldorinmentions, Type.IsAssignablewill also get the original (non-derived) type. (Type.IsSubclassOfwill not, but Type.IsSubclassOfwill not work if the base type is an interface).
  • One may want/need to check for a 'real' class: && ! assemblyType.IsAbstract. (Note that all interfaces are considered abstract, see MSDN.)
  • 正如上面提到的链接状态,这个方法在每次调用时都使用反射。因此,当对同一类型重复使用该方法时,通过加载一次可能会使其效率更高。
  • 正如Anton建议的那样,也许您可​​以(微)优化它domainAssembly.GetExportedTypes()以仅检索公开可见的类型(如果这就是您所需要的)。
  • 正如诺多林提到的,Type.IsAssignable也将获得原始(非派生)类型。(Type.IsSubclassOf不会,但Type.IsSubclassOf如果基类型是接口,则不会起作用)。
  • 人们可能想要/需要检查“真实”类:&& ! assemblyType.IsAbstract. (请注意,所有接口都被认为是抽象的,请参阅MSDN。)

回答by ADM-IT

Just create a static dictionary of derived types on start and do lookup with that. Eg. public static Dictionay<Type, Type[]> DerivedTypes { get;set; }where Type is any type you want to include in the search and Type[] is a list of derived types. Fill the dictionary up when app starts and use it during the whole life of the app.

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

回答by Jordan Webster

I ended up using the code that the top answer gave. Only thing is I wanted the code to be more readable so I wrote basically the same thing but like this instead:

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

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

In my case I used type.IsSubClassOf(MyType)because I only wanted derived types excluding the base class like mentioned above. I also needed the derived types not to be abstract (!type.IsAbstract) so I am also excluding derived abstract classes.

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