dependency injection - mvc - ¿Cuándo se eliminan las instancias inyectadas de.NET Core?
mvc dependency injection (1)
ASP.NET Core usa métodos de extensión en IServiceCollection
para configurar la inyección de dependencia, luego, cuando se necesita un tipo, usa el método apropiado para crear una nueva instancia:
-
AddTransient<T>
: agrega un tipo que se crea de nuevo cada vez que se solicita. -
AddScoped<T>
: agrega un tipo que se mantiene para el alcance de la solicitud. -
AddSingleton<T>
: agrega un tipo cuando se solicita por primera vez y lo mantiene en espera.
Tengo tipos que implementan IDisposable
y que causarán problemas si no se eliminan: en cada uno de esos patrones, ¿cuándo se llama realmente Dispose
?
¿Hay algo que deba agregar (como el manejo de excepciones) para garantizar que la instancia esté siempre dispuesta?
Los objetos resueltos tienen el mismo ciclo de vida / disposición que su contenedor, a menos que usted elimine manualmente los servicios transitorios en el código using
declaración o .Dispose()
método .Dispose()
.
En ASP.NET Core, obtiene un contenedor de ámbito que se crea una instancia por solicitud y se elimina al final de la solicitud. En este momento, las dependencias de alcance y transitorias que fueron creadas por este contenedor también se eliminarán (es decir, si implementan IDisposable
interfaz IDisposable
), que también puede ver en el código fuente here .
public void Dispose()
{
lock (ResolvedServices)
{
if (_disposeCalled)
{
return;
}
_disposeCalled = true;
if (_transientDisposables != null)
{
foreach (var disposable in _transientDisposables)
{
disposable.Dispose();
}
_transientDisposables.Clear();
}
// PERF: We''ve enumerating the dictionary so that we don''t allocate to enumerate.
// .Values allocates a ValueCollection on the heap, enumerating the dictionary allocates
// a struct enumerator
foreach (var entry in ResolvedServices)
{
(entry.Value as IDisposable)?.Dispose();
}
ResolvedServices.Clear();
}
}
Los Singletons se eliminan cuando se desecha el contenedor principal, generalmente significa cuando la aplicación se apaga.
TL; DR : Mientras no cree una instancia de los servicios de alcance / transitorios durante el inicio de la aplicación (usando app.ApplicationServices.GetService<T>()
) y sus servicios implementen correctamente la interfaz desechable (como señalada en MSDN ), no hay nada que necesite para cuidar de.
El contenedor principal no está disponible fuera del método de Configure(IApplicationBuilder app)
menos que haga algunas cosas Configure(IApplicationBuilder app)
para que sea accesible desde el exterior (que de todos modos no debería).
Por supuesto, se recomienda liberar servicios transitorios tan pronto como sea posible, especialmente si consumen muchos recursos.