Get all inherited classes of an abstract class

I have an abstract class:

abstract class AbstractDataExport { public string name; public abstract bool ExportData(); } 

I have classes that are derived from AbstractDataExport:

 class XmlExport : AbstractDataExport { new public string name = "XmlExporter"; public override bool ExportData() { ... } } class CsvExport : AbstractDataExport { new public string name = "CsvExporter"; public override bool ExportData() { ... } } 

Is it possible to do something like this? (Pseudo code :)

 foreach (Implementation imp in Reflection.GetInheritedClasses(AbstractDataExport) { AbstractDataExport derivedClass = Implementation.CallConstructor(); Console.WriteLine(derivedClass.name) } 

with an exit like

 CsvExporter XmlExporter 

?

The idea is to simply create a new class that is derived from AbstractDataExport, so I can automatically execute all implementations and add, for example, names to the drop-down list. I just want to encode a derived class without changing anything else in the project, recompile, bingo!

If you have alternative solutions: tell em.

thank

+75
inheritance reflection c #
Mar 23 2018-11-21T00:
source share
5 answers

This is such a common problem, especially in GUI applications, that I am surprised that there is no BCL class for this. This is how I do it.

 public static class ReflectiveEnumerator { static ReflectiveEnumerator() { } public static IEnumerable<T> GetEnumerableOfType<T>(params object[] constructorArgs) where T : class, IComparable<T> { List<T> objects = new List<T>(); foreach (Type type in Assembly.GetAssembly(typeof(T)).GetTypes() .Where(myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf(typeof(T)))) { objects.Add((T)Activator.CreateInstance(type, constructorArgs)); } objects.Sort(); return objects; } } 

A few notes:

  • Do not worry about the β€œcost” of this operation - you will do it only once (hopefully), and even then it is not as slow as you think.
  • You need to use Assembly.GetAssembly(typeof(T)) because your base class may be in a different assembly.
  • You need to use the criteria type.IsClass and !type.IsAbstract because it will throw an exception if you try to instantiate an interface or abstract class.
  • I like to force the listed classes to implement IComparable so that they can be sorted.
  • Your child classes must have the same constructor signatures, otherwise this will throw an exception. This is usually not a problem for me.
+113
Aug 04 '11 at 15:55
source share

Assuming all of them are defined in one assembly, you can do:

 IEnumerable<AbstractDataExport> exporters = typeof(AbstractDataExport) .Assembly.GetTypes() .Where(t => t.IsSubclassOf(typeof(AbstractDataExport)) && !t.IsAbstract) .Select(t => (AbstractDataExport)Activator.CreateInstance(t)); 
+33
Mar 23 2018-11-21T00:
source share

This may not be an elegant way, but you can Type.IsSubclassOf(AbstractDataExport) over all the classes in the assembly and call Type.IsSubclassOf(AbstractDataExport) for each of them.

+10
Mar 23 2018-11-21T00:
source share

typeof(AbstractDataExport).Assembly points to the assembly in which your types are located (provided that they are all the same).

assembly.GetTypes() provides you with all types in this assembly or assembly.GetExportedTypes() provides types that are publicly available.

Iterating over types and using type.IsAssignableFrom() gives you the type of output.

+3
Mar 23 2018-11-21T00:
source share

Ok, Reflection is your friend here. Before you implement this, you can consider the performance aspects of this: "Reflection is always expensive" :-)

0
Mar 23 2018-11-21T00:
source share



All Articles