paint-brush
3 conseils simples pour l'injection de dépendances à l'aide de Scrutor en C#par@devleader
430 lectures
430 lectures

3 conseils simples pour l'injection de dépendances à l'aide de Scrutor en C#

par Dev Leader7m2024/03/04
Read on Terminal Reader

Trop long; Pour lire

Explorez les techniques avancées d'injection de dépendances à l'aide de Scrutor en C#. Découvrez comment optimiser l'enregistrement et la résolution, implémenter la journalisation avec le modèle de décorateur et utiliser les bascules de fonctionnalités pour les implémentations de services dynamiques. Élevez vos applications ASP.NET Core avec des stratégies expertes pour une organisation et une gestion efficaces du code !
featured image - 3 conseils simples pour l'injection de dépendances à l'aide de Scrutor en C#
Dev Leader HackerNoon profile picture
0-item

L’injection de dépendances en C# est une bouée de sauvetage lors de l’organisation des dépendances, en particulier dans les applications ASP.NET Core plus complexes. Et si vous êtes déjà familier avec IServiceCollection ou si vous souhaitez simplement vous en tenir le plus possible aux offres DI déjà fournies, Scrutor en C# est une grande amélioration.


Dans cet article, je vais vous fournir un aperçu de haut niveau de l'injection de dépendances et de Scrutor en C#. Mais à partir de là, nous passons directement à 3 conseils que vous pouvez utiliser avec Scrutor et qui pourraient s'avérer très utiles dans votre candidature !


Qu’est-ce que Scrutor en C# ?

Scrutor est un puissant package NuGet en C# qui améliore l'injection de dépendances. Il simplifie l'enregistrement et la résolution des dépendances, ce qui vous permet de gérer et d'organiser plus facilement votre code.


L'injection de dépendances est une approche populaire pour configurer des applications qui favorise le couplage lâche et améliore la testabilité et la maintenabilité. Cela implique d’injecter des dépendances dans une classe plutôt que de les créer directement au sein de la classe. Cela signifie que la responsabilité de créer la dépendance n'appartient pas à la classe qui la nécessite, mais plutôt à quelqu'un au niveau de la pile d'appels. Finalement, cela pousse presque toutes les créations de dépendances au point d'entrée d'une application, ce qui la rend lourde. Cependant, les frameworks d'injection de dépendances aident à nettoyer et à organiser toute cette logique .


Scrutor va encore plus loin dans ce concept en fournissant un moyen simple et intuitif d'enregistrer et de résoudre les dépendances. Avec Scrutor, vous n'avez plus besoin d'enregistrer manuellement chaque dépendance une par une. Au lieu de cela, vous pouvez utiliser des conventions et des attributs pour automatiser le processus.

1 – Utilisation de Scrator pour l’enregistrement et la résolution

Pour illustrer comment utiliser Scrutor en C# pour l'enregistrement et la résolution, considérons un scénario simple. Imaginez que nous ayons une application qui nécessite l'utilisation de différents référentiels de données, tels que UserRepository et ProductRepostiory.


Tout d’abord, nous devons installer le package Scrutor NuGet dans notre projet. Ouvrez la console du gestionnaire de packages et exécutez la commande suivante :

 Install-Package Scrutor


Ensuite, nous devons définir nos référentiels et leurs interfaces correspondantes. Cet exemple est essentiellement vide, mais nous y ferons référence dans un instant :

 public interface IUserRepository { // Interface methods } public class UserRepository : IUserRepository { // Implementation } public interface IProductRepository { // Interface methods } public class ProductRepository : IProductRepository { // Implementation }


Maintenant, connectons nos dépendances à l'aide de Scrutor. Dans votre code de démarrage (comme dans la méthode ConfigureServices dans ASP.NET Core), ajoutez le code suivant :

 services.Scan(scan => scan .FromAssemblyOf<Startup>() .AddClasses(classes => classes.AssignableToAny( typeof(IUserRepository), typeof(IProductRepository))) .AsImplementedInterfaces() .WithScopedLifetime());


Ce code utilise la méthode Scan de Scrutor pour analyser l'assembly qui contient la classe Startup. Il filtre ensuite les classes attribuables aux interfaces IUserRepository ou IProductRepository. Enfin, il cartographie les implémentations de ces interfaces et les enregistre auprès de leurs interfaces respectives.


Maintenant, nous pouvons injecter ces dépendances dans nos classes. Par exemple, disons que nous avons une classe UserService qui nécessite IUserRepository :

 public class UserService { private readonly IUserRepository _userRepository; public UserService(IUserRepository userRepository) { _userRepository = userRepository; } // Rest of the class implementation }


En déclarant IUserRepository comme dépendance dans le constructeur, Scrutor avec IServiceCollection résoudra et injectera automatiquement l'instance UserRepository pour nous.


2 – Le modèle Décorateur – Exemple de journalisation des services

Imaginez que vous ayez une interface de service IService et une implémentation MyService . Vous souhaitez enregistrer l'entrée et la sortie de chaque appel de méthode dans MyService sans polluer sa logique métier avec des problèmes de journalisation.


Tout d’abord, définissez l’interface IService et son implémentation :

 public interface IService { void DoWork(); } public class MyService : IService { public void DoWork() { // Business logic here } }


Ensuite, créez une classe de décorateur LoggingDecorator qui implémente IService . Cette classe encapsulera le service réel et ajoutera une journalisation autour des appels de méthode délégués :

 public class LoggingDecorator : IService { private readonly IService _decorated; private readonly ILogger<LoggingDecorator> _logger; public LoggingDecorator(IService decorated, ILogger<LoggingDecorator> logger) { _decorated = decorated; _logger = logger; } public void DoWork() { _logger.LogInformation("Starting work."); _decorated.DoWork(); _logger.LogInformation("Finished work."); } }


Maintenant, utilisez Scrutor pour enregistrer votre service et son décorateur dans Startup.cs ou partout où vous configurez vos services :

 public void ConfigureServices(IServiceCollection services) { // Register the base service services.AddScoped<IService, MyService>(); // Use Scrutor to apply the decorator services.Decorate<IService, LoggingDecorator>(); // Make sure to register the ILogger or ILogger<T> dependencies if not already done }


Cette configuration utilise Scrutor pour envelopper l'enregistrement IService avec LoggingDecorator . Lors de la résolution IService , le conteneur DI fournira une instance de LoggingDecorator , qui à son tour encapsule une instance de MyService . Cette approche permet de séparer les préoccupations en gardant la logique de journalisation en dehors de votre logique métier.


3 – Basculement de fonctionnalité pour les implémentations de services

Lorsque nous construisons des systèmes complexes, il arrive souvent que nous souhaitions introduire quelque chose comme des indicateurs de fonctionnalités. Ceux-ci nous permettent d'emprunter différents chemins de code en fonction de la configuration et de ne pas avoir à recompiler et déployer une application entière. Dans certaines situations, il ne s'agit pas seulement de choisir un chemin de code différent, il s'agit d'échanger une implémentation entière de quelque chose !

Essayons ensemble un exemple ! Supposons que vous disposez d’une interface IFeatureService avec plusieurs implémentations : NewFeatureService (une nouvelle fonctionnalité expérimentale) et StandardFeatureService (la fonctionnalité actuelle et stable). Vous souhaitez basculer entre ces implémentations au moment de l'exécution en fonction d'un indicateur de configuration.


Tout d’abord, définissez l’interface IFeatureService et ses implémentations :

 public interface IFeatureService { void ExecuteFeature(); } public class NewFeatureService : IFeatureService { public void ExecuteFeature() { // New feature logic } } public class StandardFeatureService : IFeatureService { public void ExecuteFeature() { // Standard feature logic } }


Ensuite, vous avez besoin d'un moyen de déterminer quelle implémentation utiliser en fonction d'un paramètre de basculement de fonctionnalité. Il peut s'agir d'une valeur dans appsettings.json , d'un paramètre de base de données ou de toute autre source de configuration.


Maintenant, utilisez Scrutor pour enregistrer dynamiquement l'implémentation de service appropriée en fonction de la bascule de fonctionnalité :

 public void ConfigureServices(IServiceCollection services) { // Assume GetFeatureToggleValue() retrieves the current feature toggle setting var useNewFeature = GetFeatureToggleValue("UseNewFeature"); // Dynamically register the appropriate implementation based on the feature toggle if (useNewFeature) { services.AddScoped<IFeatureService, NewFeatureService>(); } else { services.AddScoped<IFeatureService, StandardFeatureService>(); } // Optional: You could combine this with the previous example // to use the decorator pattern too! // services.Decorate<IFeatureService, FeatureServiceProxy>(); } private bool GetFeatureToggleValue(string featureName) { // This method would typically check your // configuration source to determine if the feature is enabled // For simplicity, this is just a placeholder return false; // or true based on actual configuration }


Adopter une approche comme celle-ci peut nous aider à :

  • Flexibilité : permet à l'application de basculer entre les implémentations de fonctionnalités sans avoir besoin de redéployer. Vous pouvez activer ou désactiver des fonctionnalités avec une simple modification de configuration.
  • Tests en production : vous pouvez tester de nouvelles fonctionnalités dans un environnement de production avec un ensemble limité d'utilisateurs en activant la fonctionnalité pour ces utilisateurs.
  • Déploiements progressifs : aide au déploiement progressif des fonctionnalités pour surveiller l'impact et assurer la stabilité avant une version plus large.
  • Atténuation des risques : revenez rapidement à l'ancienne implémentation si des problèmes surviennent avec la nouvelle fonctionnalité, minimisant ainsi les temps d'arrêt et l'impact sur les utilisateurs.

Conclusion de Scrutor en C#

Dans cet article, je vous ai fourni 3 conseils simples pour l'injection de dépendances avec Scrutor en C#. Après un bref aperçu de ce qu'est l'injection de dépendances et de la manière dont Scrutor s'y intègre, nous sommes passés directement à nos exemples. Nous avons pu voir l'analyse des assemblys, comment décorer les dépendances et même comment envisager de signaler des fonctionnalités d'implémentations entières !


L'injection de dépendances est quelque chose qui peut grandement simplifier vos applications à mesure qu'elles deviennent de plus en plus complexes, et Scrutor peut être d'une grande aide si vous souhaitez vous en tenir à l' offre IServiceCollection intégrée de Microsoft . Si vous avez trouvé cela utile et que vous recherchez davantage d'opportunités d'apprentissage, pensez à vous abonner à ma newsletter hebdomadaire gratuite sur le génie logiciel et regardez mes vidéos gratuites sur YouTube ! Rejoignez moi et les autres membres de la communauté sur Discord !


Également publié ici.