Вопрос

У меня вопрос к свободным интерфейсам.

У нас есть несколько объектов, которые используются в качестве объектов параметров для интерфейса SQL, вот пример:

using (DatabaseCommand cmd = conn.CreateCommand(
    "SELECT A, B, C FROM tablename WHERE ID = :ID",
    SqlParameter.Int32(":ID", 1234)))
{
    ...
}

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

Вот пример, где я добавил то, что я изучаю:

SqlParameter.Int32(":ID", 1234).With(SqlParameterOption
    .Substitute
    .Precision(15)
)

Я знаю, что эти два параметра не имеют смысла для этого типа параметра, но вопрос не в этом.

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

Что если я переупорядочу их?

SqlParameter.Int32(":ID", 1234).With(SqlParameterOption
    .Precision(15)
    .Substitute
)

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

Как мне это сделать? Я совершенно не на том пути?

Когда я перечитывал вопрос, у меня возникла идея, будет ли этот другой синтаксис ниже более понятным?

SqlParameter.Int32(":ID", 1234).With
    .Precision(15)
    .Substitute

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

Советы и несколько хороших URL-адресов были бы весьма кстати, я рассмотрел много примеров, но они, как правило, показывают такие примеры:

order
    .AddFreeShipping()
    .IncludeItem(15)
        .SuppressTax();

(снято с этой страницы ) <Ч>

Изменить . Отслеживание после ответов @marxidad :

class SqlParameterOption
{
    public SqlParameterOption Precision(int p) {/* ... */; return this;}
    public SqlParameterOption Substitute() {/* ... */; return this;}
    /* ... */       
}

/* ... */
SqlParameter.Int32(":ID", 1234).With(new SqlParameterOption()
                                           .Precision(15)
                                           .Substitute());

При таком подходе С должен был бы взять объект и применить его к параметру. Я в порядке с этим.

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

SqlParameter.Int32(":ID", 1234).With
                               .Precision(15)
                               .Substitute());

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

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

Мое решение . Как говорит @marxidad , если изменения являются необратимыми и могут потенциально быть отменены, создание состояния и сбой при какой-то пункт с исключением - это путь, по которому я пойду.

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

В этом случае мой код будет выглядеть следующим образом:

SqlParameter.Int32(":ID", 1234).With(new SqlParameterOption()
                                           .Precision(15)
                                           .Substitute());

Изменить. Да, так и происходит, когда я концентрируюсь только на одной вещи.

Я не могу использовать этот синтаксис, я пойду со следующим, как предложено @marxidad : <*>

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

Это было полезно?

Решение

Методы

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

class SqlParameterOption
 {
    public SqlParameterOption Precision(int p) {/* ... */; return this;}
    public SqlParameterOption Substitute() {/* ... */; return this;}
    /* ... */       
 }

/* ... */
SqlParameter.Int32(":ID", 1234).With(new SqlParameterOption()
                                           .Precision(15)
                                           .Substitute());

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

Другие советы

Вы можете перегрузить методы . Например, если это был Substitute (). Обычно вы не можете иметь как статическую, так и экземплярную версии метода, но методы расширения могут быть полезны ... но если две версии Substitute имеют разные значения, было бы чище просто возвращать разные типы, поэтому что два варианта Substitute () не могут конфликтовать.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top