web-dev-qa-db-fra.com

Autofac - InstancePerHttpRequest vs InstancePerLifetimeScope

Quelles sont les différences entre les deux portées?

Je crée Module (s) dans chaque couche (référentiel, service, application MVC), mais pour avoir InstancePerHttpRequest, vous avez besoin de l'assemblage Autofac.Mvc.

Quelle portée dois-je utiliser dans ma couche Référentiel et Service?

56
Sam

InstancePerHttpRequest et InstancePerApiRequest font essentiellement la même chose - vous obtenez une seule instance de votre service pour chaque demande Web discrète. J'utiliserai InstancePerHttpRequest pour le reste de la réponse, mais gardez à l'esprit que ces deux sont interchangeables.

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

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

  • Le composant SingleInstance réside dans la portée racine
  • Le composant InstancePerHttpRequest réside dans une étendue appelée "AutofacWebRequest", qui est un enfant de l'étendue racine

Autofac ne permet pas la résolution à partir des étendues enfants - donc essentiellement, le service SingleInstance ne peut pas trouver le service InstancePerHttpRequest.

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

J'ai rédigé un article assez complet avec du code téléchargeable qui tente d'expliquer tout cela en détail - voir ici . Citant de l'article:

Une idée fausse courante ici est que l'enregistrement de votre composant avec InstancePerLifetimeScope dans une application WebAPI signifie que votre composant vit dans le cadre d'une demande Web - c'est-à-dire que "Lifetime" fait référence à "la durée de vie de la demande Web". Comme vous pouvez le voir ici, c'est faux.

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

Étant donné que SingletonResolvable résout son jeton à partir de la portée racine, cette instance de jeton vit dans la portée racine, et non dans la portée d'une demande Web. Je l'ai déjà dit, mais je le répète: ce jeton restera en vigueur jusqu'à ce que l'application entière soit supprimée (par exemple, le processus de travail IIS est recyclé). Tout ce qui demande un ScopeToken de la portée racine recevra une référence à ce jeton.

J'espère que cela aide - j'apprécie que cette question soit maintenant assez ancienne, mais elle est toujours très pertinente!

111
gerrod

Le seul endroit dans votre application qui soit complètement capable de prendre une décision sur la durée de vie d'un objet est à la racine de la composition.

Dans ce cas, vous avez un conflit - vous avez un module générique qui ne devrait pas avoir accès à la méthode d'extension fournie par l'intégration MVC - mais vous devez y avoir accès pour que la durée de vie soit correctement gérée. 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. Étant donné que le dernier enregistrement remplacera les enregistrements précédents, vous devriez être en bonne forme.

Je me suis en fait éloigné de la création de modules qui coexistent avec l'assembly qui contient une couche donnée pour deux raisons:

  1. Il introduit une dépendance à Autofac, dont je ne veux pas sauf à ma racine de composition
  2. Cela suggère que le module sait comment sa durée de vie doit être gérée, ce qui n'est généralement pas vrai. Si c'est le cas, pourquoi ne pas fournir une usine ou d'autres classes qui assurent cette gestion à vie?

Au lieu de cela (et dans des projets suffisamment importants pour le justifier), je crée les modules au niveau racine de la composition car à ce niveau, j'ai une connaissance explicite de la façon dont ils doivent être câblés ensemble. Parfois, je crée un Ioc Assembly qui contient les modules et qui agit comme une racine de composition par défaut - mais cela est souvent remplacé à la "vraie" racine de la composition (par exemple, la console ou l'application MVC qui extrait l'assemblage Ioc).

8
Kaleb Pederson

Dans Autofac par durée de vie scope est un moyen générique de créer des étendues personnalisées en utilisant des durées de vie imbriquées.

L'utilisation de InstancePerLifetimeScope vous donne par demande portée, qui ajoute la durée de vie du composant pour une seule demande et utilise en interne InstancePerLifetimeScrope pour ce composant.

Utilisez InstancePerLifetimeScope partout où vous en avez besoin, ou s'il est difficile d'avoir une référence à Autofac.Integration.Mvc Assemblage dans votre couche de service - créez manuellement des étendues imbriquées à chaque début de demande et utilisez InstancePerLifetimeScope.

2
whyleee