Преобразуйте множество перегрузок методов в общий метод, вопрос проектирования - PullRequest
3 голосов
/ 24 ноября 2010

Я пытаюсь реорганизовать некоторый код здесь, который был сделан ранее другими парнями, так как я нахожу это довольно непрактичным. Вот пример

protected void SetParameterValue(SqlParameter parameter, string parameterValue, bool isNullable)
{
     if ((null == parameterValue || parameterValue == NULL_STRING) && isNullable)
            parameter.Value = DBNull.Value;
     else   parameter.Value = parameterValue;
}

protected void SetParameterValue(SqlParameter parameter, int parameterValue, bool isNullable)
{
     if (parameterValue == NULL_INT && isNullable)
            parameter.Value = DBNull.Value;
     else   parameter.Value = parameterValue;
}

protected void SetParameterValue( SqlParameter parameter, Int64 parameterValue, bool isNullable)
{
     if (parameterValue == NULL_LONG && isNullable)
            parameter.Value = DBNull.Value;
     else   parameter.Value = parameterValue;
}

Как и те, есть намного больше.Теперь мне нужно было создать тот, который принимает новый тип (у которого пока нет метода для него) и решил, что, возможно, я мог бы немного почистить, сделать это лучше.Моя идея состоит в том, чтобы создать что-то вроде

protected void SetParameterValue<T>(SqlParameter parameter, T parameterValue, bool isNullable)

, однако я не знаю, каков наилучший подход, что я могу инкапсулировать в этом универсальном методе и что мне нужно будет делать в отдельных методах.Стоит ли оно того?или подход "много методов" хорошо?Что бы я получил от общего?спасибо!

Ответы [ 5 ]

3 голосов
/ 24 ноября 2010

Один из способов устранить необходимость в переключателях - это использовать какой-то словарь для хранения делегатов, которые определяют, что составляет нуль для каждого возможного типа.Хотя я думаю, что вам придется придерживаться объекта для этого.Таким образом, у вас будет словарь, и вы установите его следующим образом:

private Dictionary<Type, Func<object, bool, bool>> _nullChecks = new Dictionary<Type, Func<object, bool, bool>>();

private void SetupNullChecks(){
    _nullChecks.Add(typeof(string), (object parameterValue, bool isNullable) => { return (null == parameterValue || parameterValue.ToString() == NULL_STRING) && isNullable; });
    _nullChecks.Add(typeof(int), (object parameterValue, bool isNullable) => { return (int)parameterValue == NULL_INT && isNullable; });
    _nullChecks.Add(typeof(long), (object parameterValue, bool isNullable) => { return (long)parameterValue == NULL_LONG && isNullable; });
}

И ваш чек будет выглядеть так:

public void SetParameterValue(SqlParameter parameter, object parameterValue, bool isNullable)
{
    if (_nullChecks[parameterValue.GetType()].Invoke(parameterValue, isNullable))
        parameter.Value = DBNull.Value;
    else parameter.Value = parameterValue;
}

Хотя, как предлагают другие, измените код для использованияОбнуляемый тип будет лучше.

1 голос
/ 24 ноября 2010

Вы всегда можете сделать

Protected void SetParameterValue(SqlParameter parameter, 
 object parameterValue, bool isNullable)....

parameter.Value берет объект, поэтому минус валидация для каждого типа, вам на самом деле не нужно отделять их.метод параметра validate, который отражает и извлекает тип типа для параметра и проверяет, установлено ли значение NULL для этого типа.что-то вроде

bool IsNull (object value){
   if (value is int){
     check int..
   }
}
//this is a quick and dirty example, there are more elegant ways to handle it.

Это сокращает валидацию типа и все ваши перегрузки, а также устраняет необходимость в универсальном методе.

0 голосов
/ 24 ноября 2010

Сложно «убрать» вопрос с помощью переключателя /, если в конце отметки, кто-то должен это сделать. У вас есть возможность переопределить / инкапсулировать то, что является нулевым для объекта или класса, но вам все равно придется проверять, что является нулевым в каждой концепции.

Я не знаю, улучшит ли это ситуацию, но вы можете сначала изолировать повторение, создав метод, как сказано выше, или изолировать только проверку нулей. Последнее, что я сделал ниже:

protected void SetParameterValue(SqlParameter parameter,object parameterValue){
    if(IsParameterNull(parameterValue) && parameter.IsNullable){
        parameter.Value = DBNull.Value;
    }
    else{
        parameter.Value = parameterValue;
    }
}

List<NULLTYPE> nulls = new List<NULLTYPE>(){new NULLTYPE(NULL_INT), new NULLTYPE(NULL_LONG), new NULLTYPE(null)}
protected bool IsParameterNull(object parameterValue){
    if(nulls.Contains(parameterValue)) return true;
    else return false;
}

Задача состоит в том, чтобы создать класс NULLTYPE, который инкапсулирует ваши концепции нуля, а затем nulls.Contains(parameterValue) проверяет, существует ли значение в списке. Вы можете пойти дальше и переопределить Contains, чтобы проверить свой собственный путь, но вам нужно подумать, сколько работы вы хотите потратить на это.

0 голосов
/ 24 ноября 2010

Подход «множественных подписей» к определению метода идеально подходит - это то, что дает нам полиморфизм.Лично я предпочел бы оставить эту технику, а не рефакторинг, как вы предлагаете.

Однако, что я сделал бы, это заменил бы повторение тела метода во всех, кроме одного, вызовамиметод 'master', приводящий параметр таким образом:

protected void SetParameterValue(SqlParameter parameter, int parameterValue, bool isNullable)
{
  SetParameterValue(parameter, (Int64)parameterValue, isNullable);
}
protected void SetParameterValue(SqlParameter parameter, Int64 parameterValue, bool isNullable)
{
  if (parameterValue == NULL_INT && isNullable)
    parameter.Value = DBNull.Value;
  else
    parameter.Value = parameterValue;
}

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

0 голосов
/ 24 ноября 2010

Я думаю, что вы можете использовать обнуляемые типы вместо bool isNullable.

protected void SetParameterValue<T>(SqlParameter parameter, T parameterValue)
{
if (parameterValue == null)
  parameter.Value = DBNull.Value;
else
  parameter.Value = parameterValue;
}

И, возможно, назовите это соответственно с этой подписью. подобно SetParameter (пары, нуль) SetParameter (пары, 5)

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