DomainContext
) son instanciadas automáticamente por el motor de ASP.NET, asumiento que tienen un constructor sin parámetros. Pero claro, la inyección de dependencias se consigue precisamente pasando las dependencias como parámetros del constructor (hay otras formas, pero tampoco casan muy bien con la creación automática de la clase).Bueno, ¿y cómo "se indica lo contrario"? La solución está explicada en esta entrada de StackOverflow: básciamente se trata de decirle a la clase
DomainService
que use una factoría personalizada cada vez que necesite una instancia del servicio, cosa que se hace desde el constructor estático se la clase Global
de ASP.NET. Esa factoría personalizada es una clase que proporcionamos nosotros y desde la que podemos crear la instancia del servicio a nuestro gusto.Veamos pues cómo extender esta idea para usar inyección de dependencias en nuestros servicios RIA.
El proyecto
He creado un solución de Visual Studio sencilla de ejemplo para ilustrar el concepto. Se compone de dos proyectos Silverlight (la aplicación principal y una biblioteca de clases para el acceso a los servicios), más un proyecto web (que aloja la aplicación Silverlight) y un proyecto de bliblioteca de clases que aloja el servicio (derivado de
DomainService
). La idea es usar inyección de dependencias para suministrar una capa de acceso a datos a la clase que implementa el servicio.La solución tiene tal que este aspecto:
En enlace RIA está establecido entre el proyecto
Client.Services
de la parte cliente y el proyecto Services
de la parte servidor, quedando pues las dependencias entre proyectos tal que así:Además de las dependencias entre proyectos, es necesario añadir un par de referencias más al proyecto
MyRiaApp.Web
:- System.ServiceModel.DomainServices.Server.dll, necesario para poder acceder a la clase
DomainService
. - Microsoft.Practices.Unity.dll, se trata de Unity, el inyector de dependencias de Microsot, que es por cierto el que se usa en el proyecto.
MyRiaApp.Services
expone un servicio RIA llamado MyRiaDomainService
que contiene métodos expuestos al cliente por medio del enlace RIA. Para simplificar, en este proyecto de ejemplo sólo se expone un método, que devuelve un entero con un contador de elementos que supuestamente son objetos útiles para la aplicación. Este es el código del servicio:Tal como he mencionado al principio, el servicio usa una capa de datos para aislar el acceso al motor de persistencia (rimbombante nombre para lo que es la base de datos), representado por un interfaz llamado
IDataAccessLayer
cuyo código es este:Un posible esqueleto de implementación de
IDataAccessLayer
podría ser este:Estamos usando el mecanismo de inyección de dependencias con la clase
MyRiaDomainService
, a la que pasamos una instancia de IDataAccessLayer
en el constructor; y también con la clase IDataAccessLayer
, a la que pasamos la cadena de conexión. Ahora se trata de hacer que ASP.NET use el inyector de dependencias (Unity, en este caso) para resolver las idems a la hora de crear instancias del servicio.Inyectando
Para conseguir tal cosa, añadiremos al proyecto web una clase
Global.asax
en la que pegaremos el siguiente código (resalto las partes más interesantes):¿Qué hemos hecho aquí? Pues un par de cosas:
- Le hemos dicho a ASP.NET que use la clase
MyAppDomainServiceFactory
cada vez que necesite crear una instancia de un servicio RIA. - Hemos creado una instancia de
UnityContainer
, que queda disponible para toda la aplicación por medio deGlobal.DependencyInjector
. - Hemos creado una instancia de
DataAccessLayer
, que hemos registrado en el inyector de dependencias. - Hemos configurado
MyAppDomainServiceFactory
para que obtenga las instancias de los servicios a partir del inyector de dependencias.
De esta forma, cada vez que se requiera una instancia de un servicio, será el inyector de dependencias quien lo proporcione, encargándose de resolver cualquier dependencia existente (la dependencia de
IDataAccessLayer
en MyRiaDomainService
, en este caso.)Nótese que una ventaja adicional de este sistema es que funcionará incluso con servicios que no tengan ninguna dependencia. Por ejemplo, en paralelo a
MyRiaDomainService
tenemos un AuthenticationDomainService
que sólo tiene un constructor sin parámetros. Unity será capaz de crear una instancia de dicho servicio sin problemas, simplemente no le inyectará ninguna dependencia.Un apunte más. Estamos obteniendo la cadena de conexión para la capa de datos a partir del archivo de configuración
Web.config
(estamos haciendo una "inyección de dependencias manual" en este caso). Pego aquí el contenido de dicho archivo (la cadena de conexión es un ejemplo, claro), que de paso muestra los elementos necesarios para que funcionen los servicios RIA:Conclusión
El patrón inyección de dependencias ayuda a conseguir código legible y mantenible. Ahora ya sabes cómo usarlo en conjunción con los servicios RIA, lo cual sin duda incrementará tu felicidad en varios enteros, o no.
0 puesyocreoques:
Publicar un comentario