En artículos anteriores hemos visto una primera introducción a inyección de dependencias, a la inversión de control y discutido sobre el patrón Service Locator frente a la inyección de dependencias. Decidimos usar inyección de dependencias por constructor en un nuevo proyecto, pero ¿Cómo lo hacemos?
Existen en el mercado diferentes frameworks de resolución de dependencias, pero centraremos este artículo en el uso de Autofac. Para instalar el paquete de Autofac, pulsaremos botón derecho sobre el proyecto donde lo queramos instalar, y pulsaremos sobre la opción “Manage NuGet Packages”.
Una vez abierto el diálogo, buscaremos en el repositorio oficial el paquete y pulsaremos el botón “Install”.
Para ver cómo hacer uso de este framework, supongamos que tenemos la siguiente clase:
Vemos que nuestro servicio recibe una interfaz por constructor, pero que no tenemos un constructor vacío, así que tendremos que hacer uso de un framework de inyección de dependencias para poder resolver la dependencia definida.
Supongamos que queremos hacer uso de nuestro servicio desde una aplicación web. Lo primero que deberemos hacer es inyectar el servicio en el constructor del controlador de la aplicación web que lo vaya a utilizar, por ejemplo, HomeController:
Como se puede observar, en el controlador de la aplicación web, en ningún momento se hace mención a la inyección necesaria por la clase SomeService. No es responsabilidad del controlador tener conocimiento de esa configuración, así que no es necesaria declararla ahí.
Si probáramos de ejecutar la aplicación, nos avisaría de la imposibilidad de encontrar un constructor vacío para el controlador indicado. Hemos, por tanto, indicar cómo resolver la inyección que hemos puesto.
Para ello, en el global.asax de la aplicación web, crearemos un contenedor con donde se registrarán todas las dependencias.
Con estas tres líneas, hemos hecho lo siguiente:
- Declaración del contenedor
- Registro en el contenedor de SomeService como la interfaz ISomeService. Así, cualquier clase que use la interfaz ISomeService, sabrá que su implementación es SomeService.
- Construcción del contenedor.
Sin embargo, si ahora lanzásemos la aplicación, no funcionaría correctamente. Viendo el detalle, el controlador HomeController sabrá cómo resolver la interfaz ISomeService, ¿pero y el constructor de SomeService? Este requiere de otra interfaz que no hemos registrado. Recordemos que es necesario registrar todo aquello que el flujo de ejecución vaya a necesitar.
Así nos quedará el registro para el ejemplo planteado:
Si en lugar de usar el servicio en una aplicación web, lo quisiéramos hacer en un servicio web WCF, además de lo explicado, tendremos que cambiar también el markup del fichero svc:
Sino, tendríamos el mismo problema que si no registráramos ninguna dependencia, ya que no se encontraría ningún constructor vacío.
Como comentábamos al principio, este artículo se ha realizado haciendo uso de Autofac, pero existen múltiples opciones de frameworks de resolución de dependencias, como pueden ser Unity, Ninject, Puzzle.Nfactory, Spring.NET, entre otros.
En próximos artículos explicaremos como registrar automáticamente las dependencias sin necesidad de irlas registrando una a una.