Как стать автором
Обновить

Способы создания экземпляра наследника класса в зависимости от данных

Уровень сложностиПростой
Время на прочтение2 мин
Количество просмотров1.3K

У нас есть табличка в базе данных с поставщиками, каждому поставщику соответствует класс обработчика, который является наследником от базового класса. Надо сделать генератор для создания обработчиков.

В голову пришло три способа организации:

  1. switch .. case

  2. Добавить в табличку столбец и туда поместить постфиксы, дальше создавать объект на осное имени наследника, который должен включать этот постфикс

  3. Поместить индекс в атрибут класса-наследника и создавать объект, используя это значение

Первый способ:

    public class parcerA: ParcerBace {}

    public class parcerB: ParcerBace {}

    public abstract class ParcerBace
    {
        switch (id)
        {
          case 1: return new parcerA();
          case 2: return new parcerB();
        }
        return null;
    }

Дешево и сердито, но если этих обработчиков много, то мы получаем длинную простыню

Второй способ:

    public class parcerA: ParcerBace {}

    public class parcerB: ParcerBace {}

    public abstract class ParcerBace
    {
        public static ParcerBace creator(string postfix)
        {
            Type tFind = typeof(ParcerBace);
            Type tR = Assembly.GetAssembly(tFind).GetTypes().FirstOrDefault(t => t.IsSubclassOf(tFind) && t.Name== "parcer" + postfix);
            if (tR != null) return (ParcerBace)Activator.CreateInstance(tR);
            return null;
        }
    }

Тут довольно короткий код, но требуется следить за соответствием этих постфиксов в базе и наименованием объектов, что порождает ошибки

Третий способ:

    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
    public class IDAttribute : Attribute
    {
        public IDAttribute(int id) 
        {
            this.id = id;
        }
        public int id { get; set; }
    }

    [ID(1)]
    public class parcerA :ParcerBace {}

    [ID(2)]
    public class parcerB : ParcerBace {}

    public abstract class ParcerBace
    {
        public static ParcerBace creator(int id)
        {
            Type tFind = typeof(ParcerBace);
            Type tR = Assembly.GetAssembly(tFind).GetTypes().FirstOrDefault(t => t.IsSubclassOf(tFind) && (t.GetCustomAttribute(typeof(IDAttribute)) as IDAttribute).id == id);
            if (tR != null) return (ParcerBace)Activator.CreateInstance(tR);
            return null;
        }
    }

А теперь сравним производительность указанных способов:, создадим 1 000 000 объектов каждым из способов и сравним время. Очевидно, что от количества наследников время тоже будет зависеть

5 наследников

  1. способ 00:00.0249570

  2. способ 00:01.5358061

  3. способ 00:10.4656699

10 наследников

  1. способ 00:00.0433666

  2. способ 00:01.7637981

  3. способ 00:11.0782414

Улучшение способа 2 и 3 на основе обсуждения

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

public abstract class ParcerBace
{
    static Dictionary<string, Type> parcers;
    static ParcerBace()
    {
        Type tFind = typeof(ParcerBace);
        parcers = Assembly.GetAssembly(tFind).GetTypes().Where(t => t.IsSubclassOf(tFind) && t.Name.StartsWith("parcer")).ToDictionary(t => t.Name.Replace("parcer", ""));
    }
    public static ParcerBace creator(string postfix)
    {
        Type tR;
        parcers.TryGetValue(postfix, out tR);
        if (tR != null) return (ParcerBace)Activator.CreateInstance(tR);
        return null;
    }
}

Если предполагается много вызовов, то это даст значительный рост производительности

2. способ 10 наследников 1000000 вызовов 00:00.1450798

3. способ 10 наследников 1000000 вызовов 00:00.1883757

Теги:
Хабы:
Всего голосов 6: ↑0 и ↓6-6
Комментарии9

Публикации

Истории

Работа

Ближайшие события

19 августа – 20 октября
RuCode.Финал. Чемпионат по алгоритмическому программированию и ИИ
МоскваНижний НовгородЕкатеринбургСтавропольНовосибрискКалининградПермьВладивостокЧитаКраснорскТомскИжевскПетрозаводскКазаньКурскТюменьВолгоградУфаМурманскБишкекСочиУльяновскСаратовИркутскДолгопрудныйОнлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн
24 – 25 октября
One Day Offer для AQA Engineer и Developers
Онлайн
25 октября
Конференция по росту продуктов EGC’24
МоскваОнлайн
7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн
7 – 8 ноября
Конференция «Матемаркетинг»
МоскваОнлайн
15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань