Get all inherited classes of a generic abstract class

I am looking for a way to get all classes that inherit from a common abstract class and execute a method for each of these classes.

I followed the Change parameter type when implementing an abstract method to have class implementations that I want, something similar to this:

public abstract class AbstractRequest<TResponseData> where TResponseData : IResponseData { public abstract void Search(); public abstract GoodData BindData(TResponseData data); } public interface IResponseData { } public class AResponse : IResponseData { } public class BResponse : IResponseData { } public class A : AbstractRequest<AResponse> { public override void Search() { // get AResponse // Call to BindData() with AResponse } public override GoodData BindData(AResponse data) { // Bind the data from AResponse to GoodData } } public class B : AbstractRequest<BResponse> { public override void Search() { // Get BResponse // Call to BindData() with BResponse } public override GoodData BindData(BResponse data) { // Bind the data from BResponse to GoodData } } 

This is a working find, until I need to get all classes A and B and call the Search() method for each of the classes. With a nonequivalent abstract class, I could use the following snippet to get classes

 var instances = from t in Assembly.GetExecutingAssembly().GetTypes() where t.IsSubclassOf(typeof(AbstractRequest)) && t.GetConstructor(Type.EmptyTypes) != null select Activator.CreateInstance(t) as AbstractRequest; 

Then, how can I get all classes A and B that inherit from AbstractRequest<AResponse> and AbstractRequest<BResponse> ?

Edit: I forgot to mention. Suppose there will be many implementations like A or B and will be added over time. I would like to have an “elegant” (if possible) solution, so later, I only need to take care of the implementation of C, D, etc.

Thanks!

+7
inheritance c # abstract
source share
3 answers

In fact, getting an instance to call Search () (and only searching) can be done by splitting the abstract class:

 public abstract class AbstractRequest { public abstract void Search(); } public abstract class AbstractRequest<TResponseData> : AbstractRequest where TResponseData : IResponseData { public abstract GoodData BindData(TResponseData data); } 

And then you can use your original (not generic) code:

 var instances = from t in Assembly.GetExecutingAssembly().GetTypes() where t.IsClass && typeof(AbstractRequest).IsAssignableFrom(t) && t.GetConstructor(Type.EmptyTypes) != null select Activator.CreateInstance(t) as AbstractRequest; 

(old, ruined decision)

I think I would do something like this (untested):

 var abstractRequestTypes = (from t in Assembly.GetExecutingAssembly().GetTypes() where t.IsClass && typeof(IResponseData).IsAssignableFrom(t) select typeof(AbstractRequest<>).MakeGenericType(t)).ToList(); var instanceTypes = from t in Assembly.GetExecutingAssembly().GetTypes() where t.IsClass && abstractRequestTypes.Any(dt => dt.IsAssignableFrom(t)); 

This should cover everything in the inheritance hierarchy using a type constraint on AbstractRequest .

+2
source share

Something like this should do the trick:

 from t in Assembly.GetExecutingAssembly().GetTypes() where t.IsClass && (typeof(AbstractRequest<AResponse>).IsAssignableFrom(t) || typeof(AbstractRequest<BResponse>).IsAssignableFrom(t)) select t; 

Or if you want to get all classes that inherit from the generic AbstractRequest class, you can use:

 from t in Assembly.GetExecutingAssembly().GetTypes() where t.IsClass && t.BaseType != null && t.BaseType.GetGenericTypeDefinition() == typeof(AbstractRequest<>) select t; 
+1
source share

This worked for me on several separate projects.

 /// <summary> /// Find all subclasses of a given type via reflection /// </summary> /// <typeparam name="T">Parent class type</typeparam> /// <returns></returns> public Type[] GetAllSubclasses<T>() where T : class { Type[] types = Assembly.GetExecutingAssembly().GetTypes() .Where(t => t.IsSubclassOf(typeof (T))).ToArray(); return types; } 

To create an instance and then execute the method, you can try this template:

 // Create new instances, then use those to execute some method. foreach (Type T in GetAllSubclasses<MyType>()) { MyType mt = (MyType) Activator.CreateInstance(T); mt.MyMethod(someArgs); } 
-one
source share

All Articles