7

Con páginas regulares ASP.NET MVC, el repositorio se pasa al constructor del control. Entonces las pruebas pueden crear una instancia del controlador que pasa en un repositorio simulado.¿Cómo usar la inyección de dependencia y el patrón de repositorio con servicios web ASP.NET?

¿Cómo puedo hacer esto con los servicios web? El problema que veo es que no tenemos el equivalente de ControllerBuilder.SetControllerFactory.

¿Cuáles son las mejores prácticas para obtener mi marco de IoC (Castle) para crear una instancia de mi servicio web con la implementación de repositorio correcta?

Pensé que podría haber una manera de extender HttpHandler y cambiar la forma en que el servicio web se instancia realmente. Creo que así es como lo hace el framework MVC.

+0

Qué tecnología está usando para implementar los servicios web? ¿Servicios web ASP.NET o Windows Communication Foundation? –

+0

ASP.NET Web Services. Sin embargo, después de leer la respuesta de jrista, creo que valdría la pena examinar WCF si realmente quiero inyectar dependencias. Estoy considerando tener dos constructores, uno que tome el repositorio como parámetros (las pruebas lo llamarán) y uno por defecto que codificará: este (nuevo IRepository) y será llamado por el framework ASP.NET. –

Respuesta

1

Creo que busca el Fondo para el castillo de Windsor WCF Integración. Proporciona una implementación de ServiceHost que se encarga del proceso de construcción de las implementaciones de su servicio, utilizando el Windsor IOC.Usted puede inyectar dependencias como cualquier otra aplicación COI uso de este servicio, y convenientemente lo suficiente, su parte del proyecto Castillo:

http://www.castleproject.org/container/facilities/trunk/wcf/index.html

Si la versión del Proyecto Castillo no hace lo que se necesita hacer, no tengo mi propia instalación que creé para hacer lo mismo para Windsor antes de encontrar la versión del proyecto Castle. En general, ambos hacen lo mismo, pero ambos también abordan el problema de forma un poco diferente.

+0

Supongo que la respuesta es "no se puede usar la inyección de constructor con los servicios web de ASP.NET", así que use BuildUp (esto) o use WCF con castle. –

+1

En realidad, debería poder usar Castle Windsor con servicios de estilo ASMX (si eso es lo que quiere decir). Pensé que estabas preguntando sobre WCF, pero no veo por qué no pudiste integrar Windsor en la tubería ASMX también. Probablemente no sea tan fácil como con WCF, pero no debería ser imposible. – jrista

+0

@jrista dado que ServiceHost no está permitido en el archivo asmx, ¿tiene algún ejemplo sobre cómo implementar DI para los servicios de asmx? – Nobody

2

Esta es una buena pregunta. Tengo el mismo problema. Creo que si está creando servicios web utilizando archivos .asmx, es imposible usar la inyección de constructor. Si usaba WCF para implementar el servicio web, entonces creo que es posible.

En mi servicio web .asmx dejo que el contenedor DI establezca las dependencias estableciendo propiedades. Como mi aplicación también es una aplicación web asp.net, así es como tengo que hacerlo, porque tampoco puedo usar la inyección de constructor en formularios web. Pero estoy usando StructureMap, y tiene una función BuildUp que puede establecer las propiedades de un objeto ya creado. No es tan limpio como la inyección del constructor, pero es un buen compromiso.

Pero los servicios web se diferencian de los formularios web, porque puedo colocar la acumulación fuera del formulario web, en el evento Application_PostMapRequestHandler. Pero no he descubierto un evento que se desencadena después de que se crea la clase de servicio web. Por lo tanto, en el constructor de mi servicio web, tengo el siguiente código

ObjectFactory.BuildUp(this); 

Y eso es un patrón anti. Una clase que se inicializa mediante un contenedor DI no debe conocer el contenedor DI en sí. Pero aún no he encontrado una mejor solución.

0

Defina una clase base y use la propiedad de inyección allí. Pete ya lo dijo, pero lo harías: ObjectFactory.BuildUp (esto);

La diferencia es que lo pondría en una clase base para los servicios web, por lo que es "automático" para las implementaciones específicas.

De esta manera es una línea, por lo que no me interesaría a menos que tenga la necesidad explícita de cambiar contenedores DI en tiempo de ejecución (improbable). Si aún necesita eso, solo mueva la llamada a una clase separada que usaría el contenedor DI específico.

0

¿Hay alguna razón por la que no puede crear una clase personalizada con el constructor deseado, luego crear una instancia de un objeto de esa clase en su asmx y luego delegar toda la acción en ese objeto?

Por lo general crear ese tipo de objetos como esto:

var o = CustomClass.Create(); 

public class CustomClass 
{ 
    public static CustomClass Create() 
    { 
    return IoC.Resolve<CustomClass>(); 
    } 
} 

public static class IoC 
{ 
    public T Resolve<T>() 
    { 
    return yourStaticReferenceToPreferredContainer.Resolve<T>(); 
    } 
} 
Cuestiones relacionadas