Je crée un site ASP.NET Web API 2.1 et comme je veux injecter des dépendances directement dans les contrôleurs, j'ai créé ma propre implémentation d'IDependencyResolver afin que StructureMap gère cela pour moi.
public class StructureMapDependencyResolver : IDependencyResolver
{
public IDependencyScope BeginScope()
{
return this;
}
public object GetService(Type serviceType)
{
return ObjectFactory.GetInstance(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return ObjectFactory.GetAllInstances(serviceType).Cast<object>();
}
public void Dispose()
{
}
}
J'ai ensuite dit à l'API Web d'utiliser cette classe en ajoutant cette ligne à la méthode Application_Start dans Global.asax
GlobalConfiguration.Configuration.DependencyResolver = new StructureMapDependencyResolver();
Cela a compilé mais quand j'ai essayé d'accéder à l'une des méthodes API dans un navigateur, j'ai eu une erreur comme celle-ci
No Default Instance defined for PluginFamily System.Web.Http.Hosting.IHostBufferPolicySelector, System.Web.Http
Celui-ci a été relativement facile à résoudre car j'ai ajouté une ligne à ma configuration StructureMap
this.For<IHostBufferPolicySelector>().Use<WebHostBufferPolicySelector>();
Cependant, j'ai eu d'autres erreurs similaires pour d'autres classes System.Web.Http et bien que je puisse résoudre certaines d'entre elles, je suis coincé sur la façon de gérer 3 d'entre elles, à savoir ITraceManager, IExceptionHandler et IContentNegotiator.
Le problème est que TraceManager qui semble être l'implémentation par défaut d'ITraceManager est une classe interne et je ne peux donc pas la référencer dans ma configuration StructureMap.
Alors, est-ce que j'y vais complètement de la mauvaise façon ou y a-t-il une autre façon d'injecter ces classes internes?
Je voudrais vous donner une suggestion et une explication pourquoi ne pas suivre cette voie et comment procéder différemment (je dirais même mieux et correctement).
L'explication complète et complète de la conception inappropriée de IDependencyResolver
peut être trouvée ici: Injection de dépendances et gestion de la durée de vie avec l'API Web ASP.NET par Mark Seemann
Permettez-moi de citer ces parties essentielles:
Le problème avec IDependencyResolver
Le principal problème avec
IDependencyResolver
est qu'il s'agit essentiellement d'un Service Locator. Il y a beaucoup de problèmes avec l'anti-pattern Service Locator, mais la plupart d'entre eux que j'ai déjà décrits ailleurs sur ce blog (et dans mon livre). Un inconvénient de Service Locator sur lequel je n'ai pas encore beaucoup écrit, c'est que dans chaque appel à GetService, il n'y a aucun contexte. Il s'agit d'un problème général avec l'anti-modèle Service Locator, pas seulement avec IDependencyResolver.
Et aussi:
... le graphique de dépendance doit savoir quelque chose sur le contexte. Quelle était l'URL de la demande? Quelle était l'adresse de base (nom d'hôte, etc.) demandée? Comment partager des instances de dépendance au sein d'une même demande? Pour répondre à de telles questions, vous devez connaître le contexte et IDependencyResolver ne fournit pas ces informations.
En bref,
IDependencyResolver
n'est pas le bon crochet pour composer des graphiques de dépendance. ** Heureusement, l'API Web ASP.NET a un meilleur point d'extensibilité à cet effet. **
Ainsi, la réponse dans ce scénario serait le ServiceActivator
. Veuillez jeter un œil à cette réponse:
Un exemple de ServiceActivator
:
public class ServiceActivator : IHttpControllerActivator
{
public ServiceActivator(HttpConfiguration configuration) {}
public IHttpController Create(HttpRequestMessage request
, HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
var controller = ObjectFactory.GetInstance(controllerType) as IHttpController;
return controller;
}
}
Tout ce que nous pouvons faire avec StructureMap, est en place. Les principales fonctionnalités du framework API Web sont toujours en place ... nous n'avons pas à les pirater. Et nous utilisons également plutôt DI/IoC puis Service locator