J'ai un cours abstrait:
abstract class AbstractDataExport
{
public string name;
public abstract bool ExportData();
}
J'ai des classes qui sont dérivées de 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()
{
...
}
}
Est-il possible de faire quelque chose comme ça? (Pseudocode :)
foreach (Implementation imp in Reflection.GetInheritedClasses(AbstractDataExport)
{
AbstractDataExport derivedClass = Implementation.CallConstructor();
Console.WriteLine(derivedClass.name)
}
avec une sortie comme
CsvExporter
XmlExporter
?
L'idée est simplement de créer une nouvelle classe dérivée de AbstractDataExport pour pouvoir parcourir automatiquement toutes les implémentations et ajouter par exemple les noms à une liste déroulante. Je veux juste coder la classe dérivée sans rien changer d'autre dans le projet, recompiler, bingo!
Si vous avez des solutions alternatives: dites-leur.
Merci
C'est un problème tellement courant, en particulier dans les applications à interface graphique, que je suis surpris qu'il n'y ait pas de classe BCL pour le faire immédiatement. Voici comment je le fais.
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;
}
}
Quelques notes:
Assembly.GetAssembly(typeof(T))
parce que votre classe de base peut appartenir à un autre assembly.type.IsClass
Et !type.IsAbstract
, Car une exception sera levée si vous essayez d'instancier une classe abstraite ou une interface.IComparable
afin qu'elles puissent être triées.En supposant qu'ils soient tous définis dans le même assemblage, vous pouvez faire:
IEnumerable<AbstractDataExport> exporters = typeof(AbstractDataExport)
.Assembly.GetTypes()
.Where(t => t.IsSubclassOf(typeof(AbstractDataExport)) && !t.IsAbstract)
.Select(t => (AbstractDataExport)Activator.CreateInstance(t));
Ce n'est peut-être pas une façon élégante, mais vous pouvez parcourir toutes les classes de l'assembly et appeler Type.IsSubclassOf(AbstractDataExport)
pour chacune d'elles.
typeof(AbstractDataExport).Assembly
vous indique un assemblage dans lequel vos types sont situés (en supposant qu'ils soient tous identiques).
Assembly.GetTypes()
vous donne tous les types de cet assemblage ou Assembly.GetExportedTypes()
vous donne les types qui sont publics.
En parcourant les types et en utilisant type.IsAssignableFrom()
, vous pouvez déterminer si le type est dérivé.