ASP.NET Core utilise des méthodes d'extension sur IServiceCollection
pour configurer l'injection de dépendance, puis lorsqu'un type est nécessaire, il utilise la méthode appropriée pour créer une nouvelle instance:
AddTransient<T>
- ajoute un type qui est recréé chaque fois qu'il est demandé.AddScoped<T>
- ajoute un type qui est conservé pour l'étendue de la demande.AddSingleton<T>
- ajoute un type lors de sa première demande et le conserve.J'ai des types qui implémentent IDisposable
et qui causeront des problèmes s'ils ne sont pas supprimés - dans chacun de ces modèles quand Dispose
est-il réellement appelé?
Y a-t-il quelque chose que je dois ajouter (comme la gestion des exceptions) pour garantir que l'instance est toujours supprimée?
Les objets résolus ont le même cycle de durée de vie/suppression que leur conteneur, sauf si vous supprimez manuellement les services transitoires dans le code à l'aide de l'instruction using
ou de la méthode .Dispose()
.
Dans ASP.NET Core, vous obtenez un conteneur de portée qui est instancié par demande et supprimé à la fin de la demande. À l'heure actuelle, les dépendances étendues et transitoires créées par ce conteneur seront également supprimées (c'est-à-dire si elles implémentent l'interface IDisposable
), que vous pouvez également voir sur le code source ici .
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();
}
}
Les singletons sont éliminés lorsque le conteneur parent est éliminé, ce qui signifie généralement lorsque l'application s'arrête.
TL; DR : Tant que vous n'instanciez pas les services étendus/transitoires au démarrage de l'application (en utilisant app.ApplicationServices.GetService<T>()
) et vos services implémenter correctement l'interface jetable (comme pointé dans MSDN ) il n'y a rien dont vous devez vous occuper.
Le conteneur parent n'est pas disponible en dehors de la méthode Configure(IApplicationBuilder app)
sauf si vous faites des choses amusantes pour le rendre accessible à l'extérieur (ce que vous ne devriez pas de toute façon).
Bien sûr, il est encouragé à libérer les services transitoires dès que possible, surtout s'ils consomment beaucoup de ressources.