Question

J'ai une question avec des interfaces fluides.

Certains objets sont utilisés comme objets de paramètres pour une interface SQL. En voici un exemple:

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

Pour certains de ces paramètres, j'aimerais activer certaines options spécialisées, mais au lieu d’ajouter plus de propriétés à la méthode Int32 (qui n’en est qu’une des nombreuses), j’ai pensé que j’allais me tourner vers des interfaces fluides.

Voici un exemple où j'ai ajouté ce que je cherche à savoir:

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

Je sais que ces deux options n’ont pas de sens pour ce type de paramètre, mais ce n’est pas la question.

Dans le cas ci-dessus, Substitute devrait être une propriété statique (ou une méthode si j'ajoute quelques parenthèses) sur la classe SqlParameterOption, alors que Precision devrait être une méthode d'instance.

Et si je les réorganise?

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

Alors, le substitut devrait être la propriété d'instance et Precision la méthode statique. Cela ne compilera pas bien sûr, je ne peux pas avoir à la fois une propriété ou une méthode statique et non statique portant le même nom.

Comment je fais ça? Suis-je complètement sur la mauvaise voie ici?

En relisant la question, j'avais une idée: cette syntaxe différente ci-dessous aurait-elle plus de sens?

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

Dans ce cas, les deux méthodes seraient des méthodes d'instance sur les retours With, ce qui constituerait une classe ou une interface spécialisée pour les options SqlParameter comme celle-ci. Je ne suis pas sûr de vouloir vider la partie .With , car cela exposerait toutes les méthodes de l'objet au lieu de celles simplement fluentes .

Des conseils et quelques bonnes adresses Web seraient les bienvenus. J'ai parcouru de nombreux exemples, mais ils ont tendance à donner des exemples comme celui-ci:

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

(extrait de cette page )

Modifier : suivi après réponses De @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());

Avec cette approche, With devrait prendre l’objet et l’appliquer au paramètre. Ça me va.

Si j’utilisais la syntaxe que j’avais ajoutée à titre d’exemple, ce serait comme suit:

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

Dans ce cas, With ne sait pas quand la chaîne se termine, chaque option devra donc appliquer son effet directement.

Qu'est-ce qui est préféré? Que les options construisent un objet d’effet qui devra être appliqué plus tard, ou que chaque effet applique directement son effet?

Ma décision : Comme l’indique @marxidad , si les modifications sont irréversibles et risquent de subir un renversement, un renforcement de l’état et une défaillance un point avec une exception est la façon dont je vais aller.

Cependant, dans ce cas, je propose une approche plus simple qui modifie directement l'objet SqlParameter.

Dans ce cas, mon code ressemblera à ceci:

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

Modifier: Gah, voilà comment ça se passe lorsque je me concentre sur une seule chose.

Je ne peux pas utiliser cette syntaxe, je vais utiliser les éléments suivants, comme le suggère @marxidad :

<*>

La raison en est bien sûr que la méthode qui prend l'objet SqlParameter en tant qu'argument est incapable de gérer l'objet renvoyé par With. Ainsi, bien que l'objet SqlParameter soit construit et configuré correctement, il est devenu incompatible avec l'utilisation prévue.

Était-ce utile?

La solution

Les méthodes

de SqlParameterOption peuvent toutes être des méthodes d'instance renvoyant le même objet:

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

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

Objet: créer un état à appliquer ultérieurement ou appliquer directement à chaque appel , s'il n'y a pas de véritables effets secondaires irréversibles dans l'un ou l'autre cas, cela n'a pas d'importance et c'est à vous de décider. goût personnel. Si les options sont validées à chaque appel de méthode et qu'il est possible que vous souhaitiez l'annuler, vous souhaiterez peut-être d'abord créer l'état, puis l'appliquer. Si l'objet de paramètre effectue la validation entre les propriétés lorsque vous les appliquez, il serait peut-être préférable d'utiliser l'application directe afin d'obtenir un retour d'informations de validation correct.

Autres conseils

Vous pouvez toutefois avoir des méthodes surchargées . Par exemple, s'il s'agissait de Substitute (). Vous ne pouvez normalement pas avoir à la fois une version statique et une version instance d'une méthode, mais les méthodes d'extension pourraient être utiles ... mais si les deux versions de Substitute ont des significations différentes, il serait plus propre de simplement renvoyer des types différents, que les deux variantes de Substitute () ne peuvent pas entrer en conflit.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top