Autofac – InstancePerHttpRequest vs InstancePerLifetimeScope

Quelles sont les différences entre les deux scopes?

Je construis des Module dans chaque couche (référentiel, service, application MVC), mais pour avoir InstancePerHttpRequest vous avez besoin de l’assembly Autofac.Mvc.

Quelle étendue dois-je utiliser dans ma couche Référentiel et service?

InstancePerHttpRequest et InstancePerApiRequest font essentiellement la même chose: vous obtenez une instance unique de votre service pour chaque requête Web discrète. Je vais utiliser InstancePerHttpRequest pour le rest de la réponse, mais gardez à l’esprit que ces deux éléments sont interchangeables.

InstancePerLifetimeScope signifie qu’une nouvelle instance du service sera créée pour chaque scope de durée de vie qui demande votre service. Chaque requête Web a sa propre durée de vie, donc, dans la pratique, le plus souvent, ces deux éléments feront exactement la même chose.

La seule vraie différence vient si vous avez un service enregistré sous InstancePerHttpRequest et que vous demandez un de ces services à un autre service enregistré comme SingleInstance . Dans ce scénario:

  • Le composant SingleInstance dans l’étendue racine
  • Le composant InstancePerHttpRequest réside dans une étendue appelée “AutofacWebRequest”, qui est un enfant de l’étendue racine

Autofac n’autorise pas la résolution à partir des étendues enfants. SingleInstance service SingleInstance ne peut donc pas trouver le service InstancePerHttpRequest .

Cependant, si dans ce scénario vous aviez utilisé InstancePerLifetimeScope (au lieu d’ InstancePerHttpRequest ), vos services se résoudraient bien.

J’ai écrit un article assez exhaustif avec un code téléchargeable qui tente d’expliquer tout cela en détail – voir ici . Citant l’article:

Une idée fausse commune ici est que l’enregistrement de votre composant avec InstancePerLifetimeScope dans une application WebAPI signifie que votre composant rest dans la scope d’une requête Web, c’est-à-dire que «Durée de vie» fait référence à la durée de vie de la requête Web. Comme vous pouvez le voir ici, c’est faux.

La durée de vie de votre composant est déterminée par la scope dans laquelle il a été résolu.

Étant donné que SingletonResolvable résout son jeton à partir de l’étendue racine, cette instance de jeton se trouve dans l’étendue racine et non dans l’étendue d’une requête Web. Je l’ai déjà dit, mais je le répète: ce jeton restra actif jusqu’à ce que l’application entière soit éliminée (par exemple, le processus de travail d’IIS est recyclé). Tout ce qui demande un ScopeToken à partir de l’étendue racine recevra une référence à ce jeton.

J’espère que ça aide – j’apprécie que cette question soit maintenant assez ancienne, mais c’est quand même très pertinent!

Le seul endroit de votre application capable de prendre une décision sur la durée de vie d’un object est la racine de composition.

Dans ce cas, vous avez un conflit – vous avez un module générique qui ne devrait pas avoir access à la méthode d’extension fournie par l’intégration MVC – mais vous devez y avoir access pour que la durée de vie soit gérée correctement. Dans ce cas, si votre module peut fournir une valeur par défaut raisonnable, comme InstancePerLifetimeScope , c’est ce que je ferais au niveau du module. Ensuite, vous laissez la racine de composition remplacer ce comportement. Dans ce cas, la racine de composition changerait la durée de vie en InstancePerHttpRequest . La dernière inscription ayant priorité sur les précédentes inscriptions, vous devriez être en bonne forme.

En fait, je me suis éloigné de la création de modules qui coexistent avec l’assemblage qui contient un calque donné pour plusieurs raisons:

  1. Il introduit une dépendance sur Autofac, que je ne veux pas sauf à ma racine de composition
  2. Cela suggère que le module sait comment gérer sa durée de vie, ce qui n’est généralement pas le cas. Si tel est le cas, pourquoi ne pas fournir une usine ou d’autres classes offrant cette gestion à vie?

Au lieu de cela (et dans les projets suffisamment importants pour être justifiés), je crée les modules au niveau de la racine de composition, car à ce niveau, j’ai une connaissance explicite de la manière dont ils doivent être reliés entre eux. Parfois, je crée un assemblage Ioc qui contient les modules et qui sert de racine de composition par défaut – mais il est souvent remplacé à la racine de composition “réelle” (par exemple, la console ou l’application MVC qui Ioc assembly Ioc ).

Dans Autofac, la scope par durée de vie est un moyen générique de créer des étendues personnalisées à l’aide de durées de vie nestedes.

L’utilisation de InstancePerLifetimeScope vous permet d’ obtenir une étendue de requête qui ajoute la durée de vie des composants pour une requête unique et utilise en interne InstancePerLifetimeScrope pour ce composant.

Utilisez InstancePerLifetimeScope partout où vous en avez besoin ou en cas de problème pour avoir une référence à l’assembly Autofac.Integration.Mvc dans votre couche de service – créez manuellement des étendues nestedes à chaque début de requête et utilisez InstancePerLifetimeScope .