2008-10-20 8 views
8

J'ai une question avec des interfaces fluentes.Interfaces fluides en C#

Nous avons quelques objets qui sont utilisés comme objets de paramètres pour une interface SQL, 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, je voudrais activer certaines options spécialisées, mais au lieu d'ajouter plus de propriétés à la méthode Int32 (qui est juste l'un des nombreux), je pensais que je regarderais dans des interfaces fluides.

Voici un exemple où j'ai ajouté ce que je suis à la recherche dans:

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

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

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

Et si je les réorganise?

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

Puis Substituer doit être la propriété d'instance et Précision la méthode statique. Cela ne compilera bien sûr pas, je ne peux pas avoir à la fois une propriété statique et une propriété non statique ou une méthode avec le même nom.

Comment faire? Suis-je complètement sur la mauvaise piste ici? Pendant la relecture de la question, j'ai eu 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 seraient des méthodes d'instance sur tout ce qui, avec des rendements, ce qui serait une classe spécialisée ou de l'interface pour les options de SqlParameter comme celui-ci. Je ne suis pas sûr que je voudrais vider le . Avec partie, car cela exposerait toutes les méthodes de l'objet, au lieu de seulement les courants.

conseils et aurait quelques bonnes url la bienvenue, j'avons parcouru plus de nombreux exemples, mais ils ont tendance à montrer des exemples comme celui-ci:

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

(levée de this page)


Modifier: Followup après les 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. Cela me convient.

Si je la syntaxe j'ai ajouté à titre d'exemple, ce serait comme ceci:

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

Dans ce cas, avec sauriez pas quand la chaîne a pris fin, de sorte que chaque option à appliquer ses effectuez 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 @marxidad dit, si les changements sont irréversibles et pourraient faire l'objet d'un renversement, la construction de l'Etat et à défaut à un moment donné à une exception est la façon dont je vais.

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

Dans ce cas, mon code ressemblera à ceci:

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

Edit: Gah, c'est comment ça se passe quand je me concentre sur une seule chose.

Je ne peux pas utiliser cette syntaxe, je vais avec ce qui suit, comme le suggère @marxidad:

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

La raison en est bien sûr que la méthode qui prend l'objet SqlParameter comme argument ne peut pas pour faire face à l'objet retourné par With, donc bien que l'objet SqlParameter soit construit et configuré correctement, il est devenu incompatible avec l'utilisation prévue.

Répondre

8

méthodes SqlParameterOption's peuvent tous être des méthodes d'instance qui retourne 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()); 

Re: la construction de l'Etat à appliquer plus tard par rapport à l'application directement à chaque appel, s'il n'y a pas de véritable Side- irreverisible effets dans les deux cas, alors ce n'est pas grave et c'est à votre goût personnel. Si les options sont validées avec chaque appel de méthode et qu'il est possible que vous souhaitiez l'annuler, vous pouvez d'abord créer l'état puis l'appliquer. Si l'objet de paramètre effectue la validation entre les propriétés pour vous lorsque vous les appliquez, il peut être préférable d'utiliser l'application directe afin d'obtenir une rétroaction de validation correcte.

1

Vous pouvez cependant surchargé les méthodes. Par exemple, si c'était Substitute(). Vous ne pouvez normalement pas avoir à la fois des versions statiques et des instances d'une méthode, mais les méthodes d'extension peuvent être utiles ... mais si les deux versions de Substitute ont des significations différentes, il serait plus simple de renvoyer différents types, donc que les deux variantes de Substitute() ne peuvent pas entrer en conflit.

+0

Dans ce cas, il n'y aurait pas de conflit sur le sens, la question était plus sur la façon dont j'organise le code pour obtenir ce que je veux, syntaxiquement. La mise en place d'une instance de l'objet option résout ce problème, comme indiqué par marxidad. –

+0

Assez juste - marxidad a déjà mon +1 ;-p –

Questions connexes