Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get all inherited classes of an abstract class [duplicate]

People also ask

Can we inherit abstract class from abstract class?

Yes you can inherit abstract class from another abstract class. Yes you can inherit or extend one abstract class to another abstract class but if the class is a sealed class or single ton class at that time only inheritance cant be applicable. Yes, we can inherit an abstract class fron another abstract class.

Can abstract class get inherited?

An abstract class cannot be inherited by structures. It can contain constructors or destructors. It can implement functions with non-Abstract methods. It cannot support multiple inheritances.

Can you inherit from an inherited class?

The class whose members are inherited is called the base class, and the class that inherits those members is called the derived class. A derived class can have only one direct base class. However, inheritance is transitive.

Can abstract class inherit another after class?

Absolutely, an Abstract class can inherit from both non-abstract classes and other abstract classes. When you want any class to inherit from another class, you will want to watch out (most of the time) for the sealed modifier.


This is such a common problem, especially in GUI applications, that I'm surprised there isn't a BCL class to do this out of the box. Here's 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:

  • Don't worry about the "cost" of this operation - you're only going to be doing it once (hopefully) and even then it's not as slow as you'd think.
  • You need to use Assembly.GetAssembly(typeof(T)) because your base class might be in a different assembly.
  • You need to use the criteria type.IsClass and !type.IsAbstract because it'll throw an exception if you try to instantiate an interface or abstract class.
  • I like forcing the enumerated classes to implement IComparable so that they can be sorted.
  • Your child classes must have identical constructor signatures, otherwise it'll throw an exception. This typically isn't a problem for me.

Assuming they are all defined in the same 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));

It may not be the elegant way but you can iterate all classes in the assembly and invoke Type.IsSubclassOf(AbstractDataExport) for each one.


typeof(AbstractDataExport).Assembly tells you an assembly your types are located in (assuming all are in the same).

assembly.GetTypes() gives you all types in that assembly or assembly.GetExportedTypes() gives you types that are public.

Iterating through the types and using type.IsAssignableFrom() gives you whether the type is derived.