Get all derived types of type

Is there a better (more efficient or more convenient code;) way to find all derived types of a type? I am currently using something like:

  • get all types in used assemblies
  • check my type with all these types if it is "IsAssignable"

I was wondering if the best way to do this?

+54
c #
May 13, '09 at 12:35
source share
8 answers

I used this Linq method once to get all types inherited from base type B:

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

EDIT . It seems like this is more like rep (thus more views), let me add more details:

  • As stated above, this method uses Reflection for each call. Therefore, when reusing a method for the same type, one could make it much more efficient by loading it once.
  • As Anton suggests, maybe you can (micro) optimize it using domainAssembly.GetExportedTypes() to get only public types (if that's all you need).
  • As Noldorin mentions, Type.IsAssignable will also get the original (non-derived) type. ( Type.IsSubclassOf will not, but Type.IsSubclassOf will not work if the base type is an interface).
  • It may be required / need to check the "real" class: && ! assemblyType.IsAbstract && ! assemblyType.IsAbstract . (Note that all interfaces are considered abstract, see MSDN .)
+61
Jul 16 '13 at 15:08
source share

I am sure that the method you have proposed will become an easier way to find all derived types. Parent classes do not store any information about what their subclasses are (it would be pretty stupid if they did), which means that searching for all types cannot be avoided here.

The only recommendation is to use the Type.IsSubclassOf method instead of Type.IsAssignable to check if a particular type is derived from another. However, there may be a reason why you need to use Type.IsAssignable (for example, it works with interfaces).

+10
May 13 '09 at 12:40
source share

The only optimization you can squeeze out of this is to use Assembly.GetExportedTypes() to retrieve only public types if that happens. In addition, there is no way to speed up the process. LINQ can help with the readable side of things, but not in terms of performance.

You can short circuit to avoid unnecessary calls to IsAssignableFrom , which Reflector thinks are quite expensive, first checking to see if the type in question is the required "class". That is, you are only looking for classes, it makes no sense to test enumerations or arrays for "assignability".

+7
May 13 '09 at 12:39
source share

I think there is no better or direct way.

Better: use IsSubclassOf instead of IsAssignable .

+4
May 13 '09 at 12:41
source share

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

If you want to check wheather matchType obtained from the class represented by baseType, I would use

 matchType.IsSubclassOf(baseType) 

And if you want to check wheather matchType implements the interface provided by baseType, I would use

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

Of course, I would save baseType.ToString () as a global variable, so I would not have to call it all the time. And since you will probably need this in a context where you have many types, you can also consider using System.Threading.Tasks.Parallel.ForEach-Loop to repeat all your types ...

+4
Jun 21 '12 at 17:17
source share

If you are just interested in viewing, then .NET Reflector can do it. However, this is not so real. Do you want all types to be in the currently loaded assemblies? Assemblies referenced by the executive assembly? There are many different ways to get a list of types, and writing something that would take into account (and provide options) would be a pretty high price with relatively low benefits.

What are you trying to do? Probably the best (or at least more efficient) way to do this.

+1
May 13 '09 at 12:40
source share

Just create a static dictionary of derived types at startup and search on it. For example. public static Dictionay<Type, Type[]> DerivedTypes { get;set; } public static Dictionay<Type, Type[]> DerivedTypes { get;set; } public static Dictionay<Type, Type[]> DerivedTypes { get;set; } public static Dictionay<Type, Type[]> DerivedTypes { get;set; } where Type is any type that you want to include in the search, and Type [] is a list of derived types. Fill in the dictionary when the application starts and use it throughout the life of the application.

0
Jan 21 '19 at 17:17
source share

I ended up using code that gave the main answer. The only thing I wanted was to make the code more readable, so I wrote basically the same thing, but 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 wanted only derived types, excluding the base class, as mentioned above. I also need derived types to not be abstract ( !type.IsAbstract ), so I also exclude derived abstract classes.

0
May 17 '19 at 1:08
source share



All Articles