Замена для большого выключателя? - PullRequest
5 голосов
/ 21 февраля 2012

У меня есть страница с именем «ReportController.aspx», целью которой является создание отчета (класса) на основе параметров строки запроса

        switch (Request.QueryString["Report"])
        {                
            case "ReportA":
                CreateReportAReport("ReportA's Title");
                break;
            case "ReportB":
                CreateReportBReport("ReportB's Title");
                break;                
            case "ReportC":
                CreateReportCReport("ReportC's Title");
                break;
            case "ReportD":
                CreateReportDReport("ReportD's Title");
                break;
                ...

По сути, каждый раз, когда требуется новый отчет, будетнакладные расходы по добавлению дела и добавлению метода.Этот оператор переключения может быть очень и очень длинным.Я прочитал, что можно использовать словарь для сопоставления отчета?Как это будет выглядеть при использовании словаря (при условии, что это лучший способ).

Кроме того, метод CreateReportXReport в основном передает набор дополнительных значений QueryString в конструктор класса отчета (каждый класс отчета имеет свой конструктор).

Ответы [ 4 ]

6 голосов
/ 21 февраля 2012

Нет смысла вводить новую информацию где-нибудь; ключ заключается в том, чтобы извлечь его из кода, чтобы избежать перекомпиляции и повторного развертывания для такого тривиального изменения.

Некоторые хорошие варианты - перечислить это значение в файле конфигурации XML или, что еще лучше, в вашей базе данных.

Возможно, вы захотите заполнить словарь этими данными, независимо от источника. Это будет:

  • Упростите кеширование
  • Сделать для чистого, быстрого кода

Когда придет время вытащить ваши данные из конфигурации в код, вы добавите элементы в словарь следующим образом:

Dictionary<string, IReportCreator> = configDataGetter.GetReportDataFromDB().
    ToDictionary(r => r.Name, myReportCreatorFactory(r => r.ReportID))

В этом примере предполагается, что вы получаете данные в качестве объекта сущности и используете фабрику, которая будет использовать шаблон стратегии для вашего кода, который создает отчеты. Конечно, есть множество способов, которыми вы могли бы сделать это.

Я предполагаю, что отчеты слишком обширны, разнообразны и различны по своей природе, что вы не можете просто поместить sql и стилевые блоки в db?

Редактировать на основании комментариев оп:

Ах, Гоча. Ну, я не знаю, сколько у вас есть времени, но сколько бы вы ни вкладывали все в какую-то фабрику , у вас есть лучшие варианты, которые вы найдете позже. Я собираюсь поделиться с вами некоторыми мыслями, которые, надеюсь, помогут, от подобных вещей, которые я сделал. Каждый шаг является улучшением сам по себе, но также и детским шагом к реальному отделению логики вашего отчета от этого шелл-кода. Кроме того, я вижу, что вы уже знаете, что делаете, и я уверен, что знаю кое-что из того, что я скажу ниже, но я не знаю, что вы знаете, и это будет полезно для других.

Во-первых, извлеките всю информацию из кода в БД (если вы этого еще не сделали), и вы добавите больше полей БД (и одну или две таблицы) по мере улучшения вашей настройки.

Возможно, вы уже знаете об этом, но я упомяну об этом для других, чтобы проверить шаблон стратегии, на который я ссылаюсь выше. Вы можете иметь собственную логику каждой «функции отчета» на самом деле в конструкторе ваших различных классов стратегии. Все они наследуются от вашего базового ReportGenerator (или имеют общий интерфейс IReportGenerator). Они могут и должны иметь один и тот же конструктор; изменяющиеся параметры отчета будут обрабатываться параметром типа словарь. Реализация конструктора каждого класса будет знать типы переменных, которые нужны (из конфигурации БД), и будет соответственно приводить / использовать их.

Следующим шагом может быть действительно избавиться от вашего оператора выбора на вашем заводе, используя отражение . Вы должны будете указать имя класса как часть ваших данных конфигурации отчетов в БД (и иметь общий конструктор).

На данный момент способ добавления нового отчета довольно прост, хотя вы должны добавлять новый класс каждый раз. Это хорошо. Он отвечает принципам единоличной ответственности и принципам открытого-закрытого принципов.

Теперь есть только последний шаг удаления классов из вашего приложения , чтобы их можно было добавлять / редактировать на лету. Проверьте MEF . Это то, для чего это сделано. Некоторые вещи, которые вы можете найти в Интернете, которые вы, вероятно, не должны использовать, CodeDom (замечательно, когда больше ничего не было, но MEF лучше) и компиляция по мере необходимости сервисные функции, входящие в .NET 5. MEF - это путь.

4 голосов
/ 21 февраля 2012

Предполагая, что все отчеты реализуют IReport, вы можете сделать это, используя Func<IReport>, например:

IDictionary<string,Func<IReport>> dictToReport = new Dictionary {
    {"ReportA", () => CreateReportAReport("ReportA's Title") }
,   {"ReportB", () => CreateReportBReport("ReportB's Title") }
,   ...
};

Затем вы можете заменить коммутатор следующим кодом:

var myReport = dictToReport[Request.QueryString["Report"]]();
1 голос
/ 21 февраля 2012

Чтобы сделать это с Dictionary<string, string>, вы просто создадите его как статический кеш в содержащем типе

public class Container {
  private static Dictionary<string, Func<Report>> ReportMap = 
    new Dictionary<string, Func<Report>>();
  static Container() {
    ReportMap["ReportA"] = () => CreateReportAReport("ReportA's Title");
    ReportMap["ReportB"] = () => CreateReportBReport("ReportB's Title");
    // etc ...
  }
}

Теперь, когда карта построена, вы просто выполняете поиск в функции вместо switch

Func<Report> func;
if (!ReportMap.TryGetValue(Request.QueryString["Report"), out func)) {
  // Handle it not being present
  throw new Exception(..);
}

Report report = func();
1 голос
/ 21 февраля 2012

Я думаю, что лучше изменить этот код и преобразовать его в некоторую таблицу базы данных («Отчеты»), чтобы сохранить там список отчетов и идентификатор каждого отчета.

Вот и все.

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