获取抽象类的所有继承类

tra*_*mpi 112 c# reflection inheritance

我有一个抽象类:

abstract class AbstractDataExport
{
        public string name;
        public abstract bool ExportData();
}
Run Code Online (Sandbox Code Playgroud)

我有从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()
    {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

可以这样做吗?(伪代码:)

foreach (Implementation imp in Reflection.GetInheritedClasses(AbstractDataExport)
{
    AbstractDataExport derivedClass = Implementation.CallConstructor();
    Console.WriteLine(derivedClass.name)
}
Run Code Online (Sandbox Code Playgroud)

输出像

CsvExporter
XmlExporter
Run Code Online (Sandbox Code Playgroud)

这背后的想法是创建一个派生自AbstractDataExport的新类,这样我就可以自动遍历所有实现并将名称添加到Dropdown-List.我只是想编译派生类而不改变项目中的任何其他内容,重新编译,宾果游戏!

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

谢谢

Rep*_*Man 165

这是一个常见的问题,特别是在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;
    }
}
Run Code Online (Sandbox Code Playgroud)

几点说明:

  • 不要担心这项操作的"成本" - 你只会做一次(希望如此),即便如此,它也不会像你想象的那么慢.
  • 您需要使用,Assembly.GetAssembly(typeof(T))因为您的基类可能位于不同的程序集中.
  • 您需要使用条件type.IsClass,!type.IsAbstract因为如果您尝试实例化接口或抽象类,它将抛出异常.
  • 我喜欢强制枚举类来实现IComparable它们以便对它们进行排序.
  • 您的子类必须具有相同的构造函数签名,否则它将抛出异常.这对我来说通常不是问题.

  • 如果子类可以在不同的程序集中定义怎么办? (3认同)
  • @tobriand这将搜索所有程序集:AppDomain.CurrentDomain.GetAssemblies()。SelectMany(s =&gt; s.GetTypes())。Where(.... (2认同)

Lee*_*Lee 59

假设它们都在同一个程序集中定义,您可以执行以下操作:

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

  • 使用`t.GetConstructor(Type.EmptyTypes)!= null`作为附加约束,以防止尝试实例化没有无参数构造函数的类. (3认同)
  • 谢谢,非常有趣.需要仔细研究一下`Activator.CreateInstance` (2认同)

Wor*_*und 11

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

  • +1:我相信这几乎是唯一的解决方案. (2认同)

Fra*_*čik 5

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

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

迭代类型并使用type.IsAssignableFrom()可以确定该类型是否是派生的。