Faire abstraction d’un conteneur IoC derrière un Singleton – Vous vous trompez?

Généralement, j’aime garder une application complètement ignorante du conteneur IoC. Cependant, j’ai rencontré des problèmes où je devais y accéder. Pour résorber la douleur, j’utilise un singleton de base. Avant de courir vers les collines ou de sortir le fusil de chasse, laissez-moi passer en revue ma solution. Fondamentalement, le singleton IoC ne fait absolument rien, il délègue simplement une interface interne à transmettre. J’ai trouvé que cela rend le travail avec Singleton moins pénible.

Ci-dessous, le wrapper IoC:

public static class IoC { private static IDependencyResolver inner; public static void InitWith(IDependencyResolver container) { inner = container; } /// Container has not been initialized. Please supply an instance if IWindsorContainer. public static T Resolve() { if ( inner == null) throw new InvalidOperationException("Container has not been initialized. Please supply an instance if IWindsorContainer."); return inner.Resolve(); } public static T[] ResolveAll() { return inner.ResolveAll(); } } 

IDependencyResolver:

 public interface IDependencyResolver { T Resolve(); T[] ResolveAll(); } 

J’ai eu beaucoup de succès avec les quelques fois où je l’ai utilisé (peut-être une fois sur deux, je préfère vraiment ne pas avoir à l’utiliser du tout) car je peux injecter tout ce que je veux: Castle, un talon, des faux, etc.

Est-ce une route glissante? Est-ce que je vais rencontrer des problèmes potentiels plus tard?

J’ai vu que même Ayende implémentait ce modèle dans le code de Rhino Commons, mais je vous conseillerais de ne pas l’utiliser autant que possible. Il y a une raison pour laquelle Castle Windsor n’a pas ce code par défaut. StructureMap fait, mais Jeremy Miller s’en est éloigné. Idéalement, vous devez considérer le conteneur lui-même avec autant de suspicion que toute variable globale.

Toutefois, vous pouvez toujours configurer votre conteneur pour qu’il résolve IDependencyResolver en tant que référence à votre conteneur. Cela peut paraître fou, mais c’est beaucoup plus flexible. Rappelez-vous simplement la règle empirique selon laquelle un object doit appeler “nouveau” ou effectuer un traitement, mais pas les deux. Pour “appeler nouveau”, remplacer par “résoudre une référence”.

Ce n’est pas vraiment une classe singleton. C’est une classe statique avec des membres statiques. Et oui, cela semble une bonne approche.

Je pense que JP Boodhoo a même un nom pour ce modèle. Le modèle de passerelle statique .

Remarque: Microsoft Patterns and Practices a créé un localisateur de services commun ( http://www.codeplex.com/CommonServiceLocator ) que la plupart des principaux conteneurs IoC seront implémentés dans un proche avenir. Vous pouvez commencer à l’utiliser à la place de votre IDependencyResolver.

BTW: c’est la façon habituelle de résoudre votre problème et cela fonctionne assez bien.

Tout dépend de l’utilisation. Utiliser le conteneur comme cela s’appelle le modèle de localisateur de service. Il y a des cas où cela ne convient pas et des cas où cela s’applique.

Si vous recherchez un “modèle de localisateur de service” sur Google, vous verrez beaucoup de billets de blog disant que c’est un anti-modèle, ce qui n’est pas le cas. Le motif a simplement été surutilisé (/ maltraité).

Pour les applications métiers classiques, vous ne devez pas utiliser SL car vous masquez les dépendances. Vous avez également un autre problème: vous ne pouvez pas gérer l’état / la durée de vie si vous utilisez le conteneur racine (au lieu d’une de ses durées de vie).

Le localisateur de services est un bon choix pour les infrastructures. Par exemple, ASP.NET MVC utilise Service Locator pour pouvoir résoudre toutes les dépendances de chaque contrôleur.