Получить все унаследованные классы абстрактного класса [duplicate]

    

На этот вопрос уже есть ответ здесь:

    

У меня есть абстрактный класс:

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, чтобы я мог автоматически перебирать все реализации и добавлять, например, имена в выпадающий список. Я просто хочу кодировать производный класс, не изменяя ничего в проекте, перекомпилировать, бинго!

Если у вас есть альтернативные решения: сообщите им.

Спасибо

95 голосов | спросил trampi 24 MaramThu, 24 Mar 2011 00:12:47 +03002011-03-24T00:12:47+03:0012 2011, 00:12:47

3 ответа


0

Это настолько распространенная проблема, особенно в приложениях с графическим интерфейсом, что я удивлен, что для этого не существует класса 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, чтобы их можно было сортировать.
  • Ваши дочерние классы должны иметь идентичные сигнатуры конструктора, в противном случае он выдаст исключение. Обычно это не проблема для меня.
ответил Repo Man 4 PM00000070000001831 2011, 19:55:18
0

Предполагая, что все они определены в одной сборке, вы можете сделать следующее:

IEnumerable<AbstractDataExport> exporters = typeof(AbstractDataExport)
    .Assembly.GetTypes()
    .Where(t => t.IsSubclassOf(typeof(AbstractDataExport)) && !t.IsAbstract)
    .Select(t => (AbstractDataExport)Activator.CreateInstance(t));
ответил Lee 24 MaramThu, 24 Mar 2011 00:41:50 +03002011-03-24T00:41:50+03:0012 2011, 00:41:50
0

typeof(AbstractDataExport).Assembly сообщает вам сборку, в которой находятся ваши типы (при условии, что все они совпадают).

assembly.GetTypes() предоставляет вам все типы в этой сборке или assembly.GetExportedTypes() дает вам типы, которые являются общедоступными.

Итерация по типам и использование type.IsAssignableFrom() позволяет определить, является ли тип производным.

ответил František Žiačik 24 MaramThu, 24 Mar 2011 00:20:11 +03002011-03-24T00:20:11+03:0012 2011, 00:20:11

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132