
Normalmente los servicios usados por nuestra aplicación ASP.NET Core los registraremos en el contenedor de dependencias, para luego ir satisfaciendo los requisitos de los distintos componentes gracias a los mecanismos de inyección de dependencias que nos proporciona el framework. De estos servicios, aquellos que se registran como scoped se liberarán automáticamente al finalizar el proceso de la petición.
Sin embargo, si instanciamos manualmente un servicio durante el proceso de la petición, tendremos que encargarnos nosotros mismos de liberarlo cuando ya no sea necesario. Los que tengan un ámbito de vida corto, normalmente los crearemos y destruiremos utilizando using
en algunos de sus sabores (como bloque o con ámbito local implícito), pero cuando queremos que pueda ser compartido entre varios componentes, no es sería tan sencillo... si no fuera porque el framework ya lo ha tenido en cuenta 🙂
Para estos casos, ASP.NET Core proporciona el extensor RegisterForDispose()
, que nos permite registrar un servicio para que se libere automáticamente al finalizar la petición.
Liberando servicios al finalizar la petición
Para registrar un servicio para que se libere automáticamente al finalizar la petición, simplemente tenemos que llamar al método RegisterForDispose()
del objeto HttpResponse
de la petición HTTP actual, pasándole el servicio que queremos liberar.
Por ejemplo, si en el interior del manejador de una minimal API tenemos un servicio MyService
que queremos liberar al finalizar la petición, simplemente tenemos que hacer lo siguiente:
app.MapGet("/", (HttpContext ctx) =>
{
var myService = new MyService();
ctx.Response.RegisterForDispose(myService);
... // Hacer algo con el servicio
return "Hello World!";
});
public class MyService: IDisposable
{
public void Dispose()
{
// TODO release managed resources here
}
}
De esta forma, el servicio se liberará automáticamente al finalizar la petición HTTP, una vez que se haya enviado la respuesta al cliente.
Si en lugar del manejador de una minimal API estamos en una acción de un controlador MVC, podemos acceder directamente al objeto HttpContext
:
public class HomeController : Controller
{
public IActionResult Index()
{
var myService = new MyService();
HttpContext.Response.RegisterForDisposeAsync(myService);
... // Hacer algo con el servicio
return Ok();
}
}
Como se puede intuir, para que la llamada a RegisterForDispose()
compile, el servicio que estamos registrando debe implementar la interfaz IDisposable
. Tiene sentido que sea así, puesto que el método Dispose()
de la interfaz es el que se invoca al finalizar la petición, al igual que sucede con los servicios scoped.
Si, en cambio, se trata de una clase que implementa IAsyncDisposable
y, por tanto, tiene un método de liberación asíncrono, el método al que debemos llamar es RegisterForDisposeAsync()
:
app.MapGet("/", (HttpContext ctx) =>
{
var myService = new MyService();
ctx.Response.RegisterForDisposeAsync(myService);
... // Hacer algo con el servicio
return "Hello World!";
});
app.Run();
public class MyService: IAsyncDisposable
{
public async ValueTask DisposeAsync()
{
// TODO release managed resources here
}
}
¡Espero que os resulte de utilidad!
Publicado en: www.variablenotfound.com.
Aún no hay comentarios, ¡sé el primero!
Enviar un nuevo comentario