Hace días que tenía preparada esta entrada, pero entre el revuelo del Build y todas las novedades que se prometían, tenía guardado este artículo en la recámara por si anunciaban alguna novedad sobre el tema.
Hasta ahora para hacer inyección de dependencias en nuestras aplicaciones web, teníamos que utilizar librerías de terceros como (Unity, Autofac, Ninject, etc), pero a partir de ahora ASP.NET 5 traerá incorporado su propio contenedor de dependencias.
Este contenedor es una versión ligera, pero nos aporta soporte completo de la pila del proceso web. Se puede acceder a los servicios en el startup, en los middleware, en los filtros, en los controladores, en el model binding, etc.
El contenedor predeterminado es útil en los casos en que no se necesite ninguna capacidad de inyección avanzadas, pero si quieres utilizar un contenedor más completo, se puede utilizar la librería que más os guste gracias al IServiceProvider.
Como funciona
Como he comentado anteriormente la utilización de la inyección de dependencias en ASP.NET 5 es muy sencilla. Lo primero que tenemos que conocer es los tipos de ciclo de vida que soporta.
- Instance: Nosotros somos los responsables de pasar la instancia al contenedor, que se utilizará cada vez que necesitemos utilizar el objeto.
[sourcecode language=»csharp»]
/**************** Instance Injection ******************/
var service = new UserService();
services.AddInstance<IUserService>(service);
[/sourcecode]
- Transient: Se creará una nueva instancia cada vez que se utilice el objeto.
[sourcecode language=»csharp»]
/**************** Transient Injection *****************/
services.AddTransient<IUserService, UserService>();
[/sourcecode]
- Singleton: Tendremos una instancia tipo singleton que se reutilizará cada vez que necesitemos el objeto.
[sourcecode language=»csharp»]
/**************** Singleton Injection *****************/
services.AddSingleton<IUserService, UserService>();
[/sourcecode]
- Scope «Per-Request»: Esta es la opción clásica de los proyectos web «Per-Request» todas las llamadas al objeto utilizaran la misma instancia hasta que termine la ejecución «Scope». Las siguientes llamadas crearan nuevas instancias.
[sourcecode language=»csharp»]
/**************** Scope Injection *****************/
services.AddScoped<IUserService, UserService>();
[/sourcecode]
Tipos de Inyección
Aunque el contenedor que trae por defecto ASP.NET 5 es muy sencillo tenemos diferentes opciones para realizar nuestra inyección de dependencias.
- Inyección en el constructor: Esta seguramente es la opción más utilizada y consiste en inyectar la dependencia en el constructor, para que el encargado de pasar la dependencia sea el que instancie el objeto.
[sourcecode language=»csharp»]
private readonly IUserService Service;
public HomeController(IUserService service)
{
Service = service;
}
[/sourcecode]
- Inyección en una Propiedad: El contenedor de ASP.NET 5 se encargará de devolver el tipo correcto de la propiedad en cuestión.
[sourcecode language=»csharp»]
[Activate]
public IUserService UserService { get; set; }
public IActionResult Index()
{
var users = UserService.GetAll();
return View(users);
}
[/sourcecode]
- Inyección en una vista: Otra de las opciones que disponemos es inyectar directamente el objeto en nuestra vista.
[sourcecode language=»html»]
@using Di.Core.Interfaces
@inject IUserService service
<div class="row">
<h1>Inject from Razor</h1>
<div class="col-lg-12">
Name: <b> @service.GetName()</b>
</div>
</div>
[/sourcecode]
Custom Injection
Como he comentado antes utilizar nuestro contenedor preferido es muy fácil. Solo tenemos que modificar la función ConfigureServices para que devuelva la interface IServiceProvider.
[sourcecode language=»csharp»]
public IServiceProvider ConfigureServices(IServiceCollection services)
{…
[/sourcecode]
Para probar esta opción me he instalado la versión alpha1 de Autofac, Autofac.Dnx que soporta ASP.NET Core 5
Luego lo único que tenemos que hacer es crear el contenedor registrar los tipos que necesitemos y devolver el contenedor como un ServiceProvider.
[sourcecode language=»csharp»]
// Create the autofac container
var builder = new ContainerBuilder();
builder.Populate(services);
builder.RegisterType<UserService>().As<IUserService>();
var container = builder.Build();
return container.Resolve<IServiceProvider>();
[/sourcecode]
Extensores
Para finalizar, si queremos utilizar EF, Identity o los propios servicios de MVC.
ASP.NET 5 pone a nuestra disposición los extensores, que nos proporciona la manera de inyectar estos servicios sin complicaciones y ahorrándonos trabajo.
[sourcecode language=»csharp»]
// Add EF services to the services container.
services.AddEntityFramework(Configuration)
.AddSqlServer()
.AddDbContext<ApplicationDbContext>();
// Add Identity services to the services container.
services.AddIdentity<ApplicationUser, IdentityRole>(Configuration)
.AddEntityFrameworkStores<ApplicationDbContext>();
// Add MVC services to the services container.
services.AddMvc();
//Web API 2 Controllers
services.AddWebApiConventions();
[/sourcecode]
Bueno espero que todas estas novedades hagan que nuestras aplicaciones sean mucho menos complejas de configurar ayudándonos a utilizar la inyección de dependencias de la forma más sencilla.
Recordar que la versión actual de ASP.NET 5 es una beta y puede que cuando tengamos la versión final se hayan añadido o eliminado cosas.
Muy buen artículo Marc, gracias!