utilisation d’un gestionnaire dans l’API Web et résolution d’Unity par requête

J’utilise Unity comme infrastructure IoC et je crée un type basé sur la valeur dans l’en-tête de chaque demande dans un gestionnaire:

var container = new UnityContainer(); container.RegisterType(new InjectionConstructor(valuefromHeader)); GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container); 

Le problème est que SendAsync du SendAsync signifie que le conteneur global est écrasé par différentes requêtes et que les contrôleurs qui utilisent IFoo dans leur constructeur obtiennent les mauvaises valeurs.

1) Puis-je synchroniser SendAsync? 2) Si ce n’est pas le cas, comment puis-je créer différentes instances pour chaque demande et que le conteneur IoC puisse être résolu en toute sécurité?

J’ai consulté les articles suivants sans succès:

http://www.asp.net/web-api/overview/extensibility/using-the-web-api-dependency-resolver http://www.strathweb.com/2012/11/asp-net-web-api -and-dependencies-in-request-scope / http://benfoster.io/blog/per-request-dependencies-in-aspnet-web-api-using-structuremap

Merci d’avance.

Je suis d’accord avec l’approche de @ Steven, mais cela ne répond pas à votre question plus générale de savoir comment résoudre chaque demande.

Je vous recommande de passer à l’utilisation de UnityHierarchicalDependencyResolver, puis tout ce que vous enregistrez avec HierarchicalLifetimeManager sera résolu par demande.

Change ça…

 GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container); 

pour ça…

 GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityHierarchicalDependencyResolver(container); 

Le problème que vous rencontrez est dû au fait que vous mélangez des valeurs d’exécution avec des dépendances de conception. En général, les services que vous résolvez à partir du conteneur ne doivent pas dépendre des valeurs d’exécution de leur constructeur. Vous ne devriez pas faire cela, car les composants ont tendance à vivre beaucoup plus longtemps que les valeurs d’exécution. L’injection de valeurs d’exécution dans les composants rend beaucoup plus difficile le diagnostic et la vérification de la configuration du conteneur.

Au lieu de cela, cachez cette valeur derrière un service capable de fournir aux utilisateurs cette instance en cas de besoin. Par exemple:

 public interface IHeaderValueProvider { HeaderValue GetCurrentValue(); } 

Vous pouvez créer une implémentation pouvant être facilement enregistrée et injectée dans tout composant nécessitant cette valeur. À tout moment après la phase de construction, ces composants peuvent appeler la méthode GetCurrentValue() sur la dépendance injectée IHeaderValueProvider .

J’ai réussi à résoudre chaque demande en déclarant ma classe UnityResolver personnalisée dans la classe WebApiConfig. La classe UnityResolver utilise la classe HttpConfiguration en supposant que vous utilisez un contexte OWIN.

 public static void Register(HttpConfiguration config) { // Web API configuration and services var _container = new UnityContainer(); DependencyConfiguration.ConfigureContainer(_container); config.DependencyResolver = new UnityResolver(_container); } 

La classe ConfigureContainer est simplement une classe dans laquelle je déclare mes dépendances IOC comme indiqué ci-dessous:

 private static void RegisterReleaseEnv(IUnityContainer container) { //Repository Registration container .RegisterType(typeof(IRepository<>), typeof(GenericRepository<>), new HierarchicalLifetimeManager()); } 

Il est très important que vous utilisiez le gestionnaire de durée de vie HierarchicalLifetimeManager afin d’obtenir une nouvelle instance par demande.

La classe UnityResolver ressemble alors à ceci:

 public class UnityResolver : IDependencyResolver { protected IUnityContainer container; public UnityResolver(IUnityContainer container) { if (container == null) { throw new ArgumentNullException("container"); } this.container = container; } public object GetService(Type serviceType) { try { return container.Resolve(serviceType); } catch (ResolutionFailedException) { return null; } } public IEnumerable GetServices(Type serviceType) { try { return container.ResolveAll(serviceType); } catch (ResolutionFailedException) { return new List(); } } public IDependencyScope BeginScope() { var child = container.CreateChildContainer(); return new UnityResolver(child); } public void Dispose() { container.Dispose(); } } 

J’espère que ça aide.

Pour plus d’informations: http://www.asp.net/web-api/overview/advanced/dependency-injection