Как бы вы напали на эту проблему построения строки полиморфизма - PullRequest
1 голос
/ 17 декабря 2008

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

У меня проблема со сборкой строки для отправки объекту OLE в правильном порядке, используя метод полиморфизма из другого вопроса.

Объект OLE может принимать и получать только строки, поэтому я создаю оболочку для всех общих команд и создаю для них более .NET ощущение.

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

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

Извините за длинный пост, который я сейчас перейду к поиску.

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

Как бы вы подошли к этому?

1 Ответ

1 голос
/ 17 декабря 2008

Я думаю, что вы слишком усложняете вещи и в итоге создадите слишком много классов.

Я бы посмотрел на проблему как на менее сложную, а не на то, как вы представляете хороший интерфейс для вызывающего абонента .net. То, что существует множество возможных аргументов, не означает, что вам нужно создавать для них множество классов, по крайней мере, если возможные вариации внутри каждого аргумента не очень сложные, т.е. если значение либо есть, либо его нет, и имеет дополнительные единицы. Затем вы попадаете в эту неразбериху, когда вам необходимо знать, в каком порядке должны располагаться части команды и т. Д.

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

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

class CommandArgs 
{
    private double? _Position_x = null;
    private double? _Position_y = null;
    private String _Position_units = null;
    private double? _Width = null;
    private String _Width_units = null;
    private double? _Height = null;
    private String _Height_units = null;

    // maybe there's a better tuple-like type for this.
    public double[] Position 
    {
         set
         {
             if (value.length != 2) throw new ArgumentException("argh!");
             _Position_x = value[0];
             _Position_y = value[1];
         }
    }
    public string Position_Units
    {
         set
         {
             _Position_Units = value;
         }
    }
    public double Width
         set
         {
             _Width = value;
         }
    }
    public double Height
         set
         {
             _Height = value;
         }
    }
    public string Width_Units
         set
         {
             _Width = value;
         }
    }
    public string Height_Units
         set
         {
             _Height = value;
         }
    }
    // ....
    public override string ToString()
    {
         return 
             ( _Position_x != null ? string.Format(" Position ({0},{1})",_Position_x, _Position_y ) : "" )
             + ( _Height != null ? string.Format(" Height {0}")
                   + ( _Height_Units != null ? string.Format(" Units {0}", _Height_Units) : "" )
             + ( _Width != null ? string.Format(" Width {0}")
                   + ( _Width_Units != null ? string.Format(" Units {0}", _Width_Units) : "" )
         // ...
         ;
    }
}

Если вы предпочитаете, вы можете создавать методы вместо свойств, чтобы вы могли установить значение и единицы измерения одновременно.

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

private string FormatUnits(string units)
{
    return units == null ? "" : string.Format(" Units {0}", units);
}
private string FormatSingleValueArgument(string argName, object argValue, string units)
{
    if (argValue == null) return "";
    return string.Format(" {0} {1}", argName, argValue) + FormatUnits(units);
}

делает ToString () похожим на это:

         return 
             ( _Position_x != null ? string.Format(" Position ({0},{1})",_Position_x, _Position_y ) : "" )
             + FormatSingleValueArgument("Height", _Height, _Height_Units) 
             + FormatSingleValueArgument("Width", _Width, _Width_Units) 
         // ...
         ;

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

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