获取抽象类的所有继承类

时间:2011-03-23 21:12:48

标签: c# reflection inheritance

我有一个抽象类:

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的新类,这样我就可以自动遍历所有实现,并将名称添加到Dropdown-List。 我只想编写派生类而不更改项目中的任何其他内容,重新编译,宾果!

如果您有其他解决方案:告诉他们。

由于

4 个答案:

答案 0 :(得分:151)

这是一个常见的问题,特别是在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,以便对它们进行排序。
  • 您的子类必须具有相同的构造函数签名,否则会抛出异常。这对我来说通常不是问题。

答案 1 :(得分:49)

假设它们都在同一个程序集中定义,您可以这样做:

IEnumerable<AbstractDataExport> exporters = typeof(AbstractDataExport)
    .Assembly.GetTypes()
    .Where(t => t.IsSubclassOf(typeof(AbstractDataExport)) && !t.IsAbstract)
    .Select(t => (AbstractDataExport)Activator.CreateInstance(t));

答案 2 :(得分:11)

它可能不是优雅的方式,但您可以迭代程序集中的所有类并调用Type.IsSubclassOf(AbstractDataExport)  对于每一个。

答案 3 :(得分:3)

typeof(AbstractDataExport).Assembly会告诉您类型所在的程序集(假设所有类型都相同)。

assembly.GetTypes()为您提供该程序集中的所有类型,或assembly.GetExportedTypes()为您提供公开的类型。

迭代类型并使用type.IsAssignableFrom()为您提供类型是否已派生。