抽象クラスがあります:
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 から派生した新しいクラスを作成し、すべての実装を自動的に反復処理して、たとえば名前をドロップダウン リストに追加できるようにすることです。プロジェクト内の他の部分を変更せずに派生クラスをコーディングし、再コンパイルするだけで完了です。
代替の解決策がある場合は、それを伝えてください。
ありがとう
ベストアンサー1
これは、特に 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;
}
}
いくつかの注意事項:
- この操作の「コスト」については心配しないでください。この操作は 1 回だけ実行され (うまくいけば)、その場合でも思ったほど遅くはありません。
Assembly.GetAssembly(typeof(T))
基本クラスが別のアセンブリにある可能性があるため、を使用する必要があります。- インターフェースまたは抽象クラスをインスタンス化しようとすると例外がスローされるため、
type.IsClass
基準を使用する必要があります。!type.IsAbstract
IComparable
列挙されたクラスを強制的に実装して、ソートできるようにするのが好きです。- 子クラスには同一のコンストラクター シグネチャが必要です。そうでない場合は例外がスローされます。これは通常、私にとっては問題ではありません。