4

In a proof-of-concept project I'm working on, I have a generic abstract class that I expect to be extended by a number of child classes:

public abstract class Pet {
    public abstract string PetTypeName {get;}
}

public class Dog : Pet {
    public override string PetTypeName { get { return "Dog"; } }
}

I'd like to have a static collection populated with all of the subtypes of this class:

public static List<Type> AllPetTypes = new List<Type> {
    typeof(Dog),
    typeof(Cat),
    //...
};

But this just adds one more step when we want to introduce a new subtype, and it's error prone because it's just one more thing a programmer can forget to do at runtime. How can I create a collection like this automatically, including every type in my assembly that inherits the given parent class?

Edit

In response do the question of what I would use this for:

Because we have multiple clients that use the same SaaS product, but with access to different subsets of portal "channels," it can be difficult to track how the user got to a particular page, and where they should be sent once they click "Done."

So I'm brainstorming architecture possibilities for an ASP.NET portal, where each page is really an enhanced user control that accepts a specific, strongly-typed class to hold its parameters, and all of the tasks involved in tracking breadcrumbs, URL creation, and such is abstracted away into the framework. So the framework needs to be aware of all of the controls that can be handled as if they were pages. Ideally, creating a new user control in the framework and making its code-behind class extend a certain base class would be sufficient to register that control as a new page in the system.

Which brings me to my next question: will finding the types in the given assembly, using the techniques mentioned in the proposed solutions to this question, work in the context of an ASP.NET web project where types are declared in the code-behind? I'm not really sure at what point the user controls get compiled, or if they are considered part of the web project's assembly. Does anyone have additional insights? (Should I make this a new question?)

Community
  • 1
  • 1
StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315

3 Answers3

13
var targetAssembly = Assembly.GetExecutingAssembly(); // or whichever
var subtypes = targetAssembly.GetTypes().Where(t => t.IsSubclassOf(typeof(Pet)));
mqp
  • 70,359
  • 14
  • 95
  • 123
3

You could start with something like this. This will get you all the types in the same assembly as the defining type that derive from the defining type.

class Aware {
    public static readonly IEnumerable<Type> AllTypes;
    static Aware() {
        Type awareType = typeof(Aware);
        allTypes = Assembly.GetAssembly(awareType)
                           .GetTypes()
                           .Where(t => awareType.IsAssignableFrom(t));        
    }
}

Test:

class Foo : Aware { }
class Bar : Aware { }

foreach (var type in Aware.AllTypes) {
            Console.WriteLine(type);
}

Output:

Aware
Foo
Bar

I'm most curious to know what you would use this for.

jason
  • 236,483
  • 35
  • 423
  • 525
0
Assembly.GetExecutingAssembly().GetTypes().Where(t => t.IsSubclassOf(typeof(parentClass)))
Sebastian Krysmanski
  • 8,114
  • 10
  • 49
  • 91
Paul Creasey
  • 28,321
  • 10
  • 54
  • 90