私には抽象クラスがあります:
abstract class AbstractDataExport
{
public string name;
public abstract bool ExportData();
}
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()
{
...
}
}
このようなことをすることは可能ですか? (擬似コード:)
foreach (Implementation imp in Reflection.GetInheritedClasses(AbstractDataExport)
{
AbstractDataExport derivedClass = Implementation.CallConstructor();
Console.WriteLine(derivedClass.name)
}
のような出力で
CsvExporter
XmlExporter
?
この背後にある考え方は、AbstractDataExportから派生した新しいクラスを作成するだけであるため、すべての実装を自動的に反復処理し、たとえばドロップダウンリストに名前を追加できます。私は、プロジェクトの他の何も変更せずに、派生クラスをコーディングし、再コンパイル、ビンゴしたいだけです!
代替ソリューションがある場合:emに伝えます。
ありがとう
これは、特にGUIアプリケーションでは非常に一般的な問題であるため、これをすぐに実行できるBCLクラスがないことに驚いています。ここに私がそれをする方法があります。
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;
}
}
いくつかのメモ:
Assembly.GetAssembly(typeof(T))
を使用する必要があります。type.IsClass
および!type.IsAbstract
を使用する必要があります。IComparable
を強制的に実装して、ソートできるようにします。それらがすべて同じアセンブリで定義されていると仮定すると、次のことができます。
IEnumerable<AbstractDataExport> exporters = typeof(AbstractDataExport)
.Assembly.GetTypes()
.Where(t => t.IsSubclassOf(typeof(AbstractDataExport)) && !t.IsAbstract)
.Select(t => (AbstractDataExport)Activator.CreateInstance(t));
それはエレガントな方法ではないかもしれませんが、アセンブリ内のすべてのクラスを繰り返して、それぞれに対してType.IsSubclassOf(AbstractDataExport)
を呼び出すことができます。
typeof(AbstractDataExport).Assembly
は、タイプが配置されているアセンブリを示します(すべてが同じであると仮定)。
Assembly.GetTypes()
はそのアセンブリのすべての型を提供し、_Assembly.GetExportedTypes()
はパブリックな型を提供します。
タイプを繰り返し処理し、type.IsAssignableFrom()
を使用すると、タイプが派生しているかどうかがわかります。