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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…