2008-10-20 10 views
8

Tengo una pregunta con interfaces fluidas.interfaces de fluido en C#

Tenemos algunos objetos que se utilizan como objetos de parámetros para una interfaz SQL, he aquí un ejemplo:

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

Para algunos de estos parámetros, me gustaría permitir que algunas opciones especializadas, pero en lugar de añadir más propiedades para el método Int32 (que es solo una de muchas), pensé en buscar interfaces fluidas.

He aquí un ejemplo en el que he añadido lo que estoy buscando en:

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

Sé que estas dos opciones no tiene sentido para este tipo de parámetro, pero eso no es lo que la pregunta se refiere.

En el caso anterior, Substitute debería ser una propiedad estática (o método si simplemente agrego algunos paréntesis) en la clase SqlParameterOption, mientras que Precision debería ser un método de instancia.

¿Qué pasa si ellos reordeno?

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

Entonces Sustituto debería ser la propiedad de la instancia y Precisión del método estático. Esto no compilará, por supuesto, no puedo tener una propiedad o método estático y no estático con el mismo nombre.

¿Cómo puedo hacer esto? ¿Estoy completamente en el camino equivocado aquí?

Si bien volver a leer la pregunta, tuve una idea, sería esta sintaxis diferente a continuación más sentido?

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

En este caso ambos serían los métodos de instancia en lo que sea con retornos, lo que sería una clase especializada o interfaz de opciones SqlParameter como este. No estoy seguro de que me gustaría volcar el .Con parte, ya que esto podría exponer todos los métodos del objeto, en lugar de sólo los fluidos queridos.

asesoramiento y una buena url de que sería muy bienvenida, he fregado durante muchos ejemplos, pero tienden a mostrar ejemplos como este:

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

(levantado de this page)


Editar: Seguimiento después de respuestas Desde @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()); 

Con este enfoque, con tendrían que tomar el objeto, y aplicarlo al parámetro. Estoy bien con eso.

Si usara la sintaxis he añadido como un ejemplo, sería así:

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

En este caso, no habría Con saber cuándo terminó la cadena, por lo que cada opción tendría que aplicar su efecto directamente.

¿Qué prefiere? ¿Que las opciones construyen un objeto de efecto que tendrá que aplicarse más tarde, o que cada efecto aplica su efecto directamente?

Mi decisión: Como @marxidad dice, si los cambios son irreversibles y potencialmente podrían ser objeto de una inversión, la construcción de estado y en su defecto en algún momento con una excepción es la manera voy a ir.

Sin embargo, en este caso, voy con un enfoque más simple que modifica el objeto SqlParameter directamente.

En este caso, el código se verá así:

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

Editar: Gah, que es lo que pasa cuando me concentro en una sola cosa.

no puedo utilizar esa sintaxis, voy a ir con lo siguiente, según lo sugerido por @marxidad:

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

La razón es, por supuesto, que el método que toma el objeto SqlParameter como un argumento no puede para hacer frente al objeto devuelto por With, así que, aunque el objeto SqlParameter se construye y configura correctamente, se volvió incompatible con el uso previsto.

Respuesta

8

SqlParameterOption's métodos pueden ser todos los métodos de instancia que devuelve el mismo objeto:

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 construcción de un estado a ser aplicado más tarde frente a la aplicación directa con cada llamada, si no hay un lado- irreverisible reales efectos en ambos casos, entonces no importa y depende de su gusto personal. Si las opciones se confirman con cada llamada a un método y existe la posibilidad de que desee deshacer eso, es posible que desee construir primero el estado y luego aplicarlo. Si el objeto del parámetro hace la validación entre propiedades a medida que las aplica, entonces sería mejor ir con la aplicación directa para que pueda obtener los comentarios de validación de manera correcta.

1

Puede haber sobrecargado métodos though. Por ejemplo, si era Sustituto(). Normalmente no puede tener versiones estáticas y de instancia de un método, pero los métodos de extensión pueden ser de alguna utilidad ... pero si las dos versiones de Substitute tienen diferentes significados, sería más simple simplemente devolver diferentes tipos, por lo que que las dos variantes de Substitute() no pueden entrar en conflicto.

+0

En este caso no habría conflicto de significado, la pregunta era más acerca de cómo organizo el código para obtener lo que quiero, en cuanto a la sintaxis. La actualización de una instancia del objeto de opción resuelve ese problema, como lo muestra marxidad. –

+0

Lo suficientemente justo - marxidad ya tiene mi +1 ;-p –