web-dev-qa-db-fra.com

Pourquoi utiliser un conteneur DI tiers sur le conteneur DI ASP.NET Core intégré?

Comme actuellement, il y a un manque de documentation sur le sujet DI - injection de dépendance . Quels sont les avantages/inconvénients de l'utilisation de la DI intégrée par rapport aux solutions existantes comme (Ninject, Autofac, StructureMap)? Et quelles sont les limitations actuelles de l'injection de dépendance par défaut (le cas échéant)?

De plus, quelqu'un peut-il m'aider à comprendre quelle est la différence entre ces enregistrements?

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<IService, Service>();
    services.AddScoped<IService, Service>();
    services.AddSingleton<IService, Service>();
    services.AddInstance(service);
}
40
Andriy Horen

Pour le développement de produits de toute application de taille raisonnable qui pratique un couplage lâche et suit les principes SOLID, le conteneur DI de .NET Core n'est pas adapté, car:

  • Cela ne vous aide pas à vérifier votre configuration, ce qui rend très difficile le diagnostic des problèmes provenant de mauvaises configurations courantes. Dans une application de taille raisonnable, il est en fait assez difficile de repérer ces erreurs vous-même.
  • Il est impossible d'appliquer préoccupations transversales à l'aide d'intercepteurs ou décorateurs de manière maintenable. Cela rend la maintenance d'une application de taille raisonnable très coûteuse.
  • Bien qu'il prenne en charge le mappage d'abstractions génériques ouvertes sur des implémentations génériques ouvertes, son implémentation est plutôt naïve et ne peut pas fonctionner avec des types génériques avec des contraintes de type, des mappages de types génériques plus complexes et des variances.
  • Il est impossible de faire des enregistrements conditionnels/contextuels, de telle sorte que les enregistrements ne soient injectés qu'à un certain ensemble de consommateurs, tout en utilisant le câblage automatique. par exemple. avec deux composants Service1 et Service2 que les deux dépendent de ILogger, vous voudrez peut-être injecter Service1 avec NullLogger et Service2 avec FileLogger, ou vous voulez Service1 à injecter avec Logger<Service1> et Service2 avec Logger<Service2>.

La principale raison de ces limitations est que le conteneur intégré a pour objectif de fournir des capacités DI en particulier au cadre lui-même, tout en maintenant ses fonctionnalités au minimum dans l'espoir que des conteneurs DI plus matures pourraient s'intégrer avec ça. En d'autres termes, il agit comme un dénominateur le moins commun (LCD). En raison de sa fonction LCD LCD, il ne peut jamais devenir un conteneur DI à taille réelle qui est pratique pour le développement d'applications.

Si vous commencez avec un nouveau projet simple, mon conseil est d'appliquer Pure DI (ce qui signifie des composants câblés à la main à l'intérieur de Composition Root sans en utilisant un conteneur) et résolvez vos types en branchant votre IControllerActivator personnalisé . Plus tard, lorsque des fonctionnalités telles que l'enregistrement automatique et l'interception amélioreraient la maintenabilité de votre racine de composition, passez à l'une des bibliothèques DI établies qui correspond à vos besoins.

45
Steven

Ici, il est expliqué:

  • Transitoire - Une nouvelle instance est créée à chaque fois
  • Portée - Une seule instance est créée dans la portée actuelle. Il est équivalent à Singleton dans la portée actuelle
  • Singleton - Une seule instance est créée et elle agit comme un singleton
  • Instance - Une instance spécifique est donnée tout le temps. Vous êtes responsable de sa création initiale

La version Alpha avait ces limitations:

  • Il prend uniquement en charge l'injection de constructeur
  • Il ne peut résoudre les types qu'avec un et un seul constructeur public
  • Il ne prend pas en charge les fonctionnalités avancées (comme la portée par thread ou la découverte automatique)

Si vous n'écrivez pas, le conteneur DI par défaut du produit devrait être suffisant pour vous. Dans d'autres cas, vous pouvez essayer des bibliothèques que vous avez déjà mentionnées qui ont des fonctionnalités avancées.

Mon conseil serait de commencer par celui par défaut et de changer l'implémentation quand (si) vous frappez quelque chose que vous ne pouvez pas faire avec.

17
Marko M.

Quelle est la différence entre ces inscriptions?

  • Transitoire - instancié à chaque fois qu'il est récupéré
  • Portée - instanciée une fois par demande http et sera disponible pour la durée de vie de la demande http
  • Singleton - instancié une fois et sera disponible pendant toute la durée de vie de votre application
  • Instance - équivalent à singleton sauf que vous fournissez l'instance d'objet au lieu du cadre créant l'instance

Source: http://www.khalidabuhakmeh.com/asp-vnext-dependency-injection-lifecycles , http://dotnetliberty.com/index.php/2015/10/15/asp-net-5-mvc6-dependency-injection-in-6-steps /

6
Michael

Pour répondre à votre première question: il semble que ASP.NET docs ont été mis à jour et indiquent maintenant clairement quel est chaque type d'enregistrement pour:

Les services ASP.NET peuvent être configurés avec les durées de vie suivantes:

Transitoire

Des services transitoires à vie sont créés chaque fois qu'ils sont demandés. Cette durée de vie fonctionne mieux pour un service léger et sans état.

Portée

Les services à vie étendus sont créés une fois par demande.

Singleton

Les services à vie Singleton sont créés la première fois qu'ils sont demandés, puis chaque demande suivante utilise la même instance. Si votre application nécessite un comportement singleton, il est recommandé d'autoriser le conteneur de services à gérer la durée de vie du service au lieu d'implémenter le modèle de conception singleton et de gérer vous-même la durée de vie de votre objet dans la classe.

Instance [pre RTM uniquement!]

Vous pouvez choisir d'ajouter une instance directement au conteneur de services. Si vous le faites, cette instance sera utilisée pour toutes les demandes suivantes (cette technique créera une instance de portée Singleton). Une différence clé entre les services d'instance et les services Singleton est que le service d'instance est créé dans ConfigureServices, tandis que le service Singleton est chargé paresseux la première fois qu'il est demandé.


Mis à jour en RTM

Notez que dans Asp.Net Core RTM docs L'instance a été supprimée. L'instance est fondamentalement la même chose que Singleton, mais ils avaient une sémantique d'initialisation différente (Singleton était chargé paresseusement) Mais maintenant il n'y a pas d'API AddInstance, seulement AddSignleton qui peut prendre une instance déjà créée.

5
NickAb