2011-09-26 2 views
1

У меня есть объект с двумя свойствами: Text и Type.Избегайте жесткого кодирования в операторе switch

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

Однако теперь я хочу запустить метод Utility для очистки поля объекта, на основе которого Type объект (например, добавляет 'http: //', если его URL-адрес).

Есть ли способ сделать это в классе Utilities без жесткого кодирования типов в инструкции switch или if else block.

switch (type) 
{ 
    case 1: 
     TidyUrl(); 
    case 2: 
     TidyUsername(); 
    case 3: 
     TidyID(); 
    default: 
     break; 
} 

В этом примере я жестко прописывать идентификаторы из базы данных («Тип» таблицы), которая никогда не может быть хорошей вещью!

Есть ли лучший способ сделать это?

+0

Я использую интерфейсы и фабрики, перечисления или имена методов в базе данных, похоже, не обойти логику if/else, которая понадобится где-то, чтобы сказать, что есть, и это та часть, которую я не могу заплатить d - способ избежать жесткого кодирования. – finoutlook

ответ

2

Традиционно это обрабатывается с использованием общего интерфейса и динамически создает конкретную реализацию для выполнения фактической работы.

, например:

public interface ITidy 
{ 
    string Tidy(string input); 
} 

затем реализации

public class UrlTidy : ITidy 
{ 
    public string Tidy(string input) 
    { 
     // do whatever you need to the url 
    } 
} 

И так далее для других видов уборки. Теперь вам нужно создать экземпляр подходящего конкретного класса (UrlTidy, IdTidy и т. Д.) От типа, на который вы смотрите. Один из способов сделать это может заключаться в том, чтобы поместить имя класса в базу данных вместе с типом и использовать отражение для создания правильной реализации ITidy. Другой ват должен иметь класс Factory, который использует некоторый другой метод для создания экземпляра справа ITidy на основе типа.

+0

Ввод имени класса или метода в базу данных похож на hardcoding наоборот. Однако это может быть предпочтительнее. – finoutlook

+0

@finoutlook - нет ничего такого, как hardcoding. Это полная противоположность, позволяющая динамически расширять типы (при условии, что вы выпускаете новую сборку, содержащую этот класс). Это сродни подключаемой системе, позволяющей расширить возможности вашего приложения, не отпуская энтузиазм программного обеспечения. – Jamiec

+0

Да, я вижу преимущество этого в базе данных. Делает техническое обслуживание намного проще, и вы правы, его можно изменить динамически. – finoutlook

4

Вы можете использовать перечисление, чтобы помочь с удобочитаемостью.

enum MyTypes 
{ 
URL = 1, 
UserName = 2, 
Id = 3, 
} 

switch (myType) 
{ 
    case MyTypes.URL: 
     TidyUrl(); 
    case MyTypes.UserName: 
     TidyUsername(); 
    case MyTypes.Id: 
     TidyID(); 
    default: 
     break; 
} 

Это перечисление должно быть согласовано с базой данных.

+0

Да, я делал это в прошлом, но, похоже, он просто поставил ту же проблему (сохраняя идентификаторы в синхронизации) в другом месте. – finoutlook

+0

@finoutlook - Но по крайней мере это _clear_, где это место. По моему опыту, вы должны иметь сопоставление _somewhere_ в базе кода. – Oded

+0

Да, я согласен с его ясностью (и мог группировать другие сопоставления вместе, например, в классе Enumerators) и лучше, чем распространяться через код. – finoutlook

3

Один из способов - использовать полиморфизм. У вас будут отдельные классы для каждого из ваших «типов», и они будут реализовывать общий интерфейс (или иметь общий базовый класс) с таким методом, как Tidy, где каждый будет выполнять свою собственную логику.

+2

И метод фабрики, который будет искать тип, закодированный в БД, и создать новый объект этого типа. Возможно, с помощью оператора 'switch';) – Oded

+0

@Oded - Точно, независимо от того, какой вариант, мне нужно будет связать мой код напрямую с тем, что находится в DB – finoutlook

+1

Да, это правда; но этот метод позволяет избежать распространения этих операторов switch. Вам нужно только _one_. Или _none_, если вы предпочитаете использовать отражение ... –

0

Вы можете использовать enum Type, но их постоянные значения будут определены во время компиляции. Вы можете поместить проверку инвариантности класса в enum, чтобы убедиться, что они совместимы с базой данных.

Но как их наличие в базе данных делает его расширяемым?

+0

Я думаю, что ваш вопрос хорош в том, почему его расширяемость. Существует ограниченное количество методов, но некоторые из типов в базе данных могут использовать одни и те же методы, например. новый тип 'UrlWithQuerystring' может использовать тот же метод' TidyUrl() '. – finoutlook

+0

Если вы увлечены не жестким кодированием номеров, то решение, которое я изложу выше, должно работать хорошо. Бонусные баллы, если вы можете сделать отдельные классы для каждого типа, поместите класс typeid и handler в таблицу базы данных и инициализируйте объекты обработчиков и сохраните их в реестре при запуске. –

0

Как Одед сказал использовать перечисление:

public enum Types 
{ 
    Type1 = 1, 
    Type2 = 2, 
    Type3 = 3 
} 

Вы можете отдать свой переменную типа в перечислении, имея целые карты с идентификаторами базы данных:

switch ((Types)type) 
{ 
    case Types.Type1: 
     break; 
    case Types.Type2: 
     break; 
    ... 
} 

Надежда, что помогает

Смежные вопросы