在Web API中使用Handler并根据请求解析Unity

我使用Unity作为我的IoC框架,我正在基于处理程序中每个请求的标头中的值创建一个类型:

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

问题是处理程序的SendAsync意味着全局容器被不同的请求覆盖,并且在构造函数中使用IFoo的控制器获取的值不正确。

1)我可以使SendAsync同步吗? 2)如果没有,如何为每个请求创建不同的实例并让IoC容器安全地解析?

我查看了以下文章但没有成功:

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

提前致谢。

我同意@ Steven的方法,但这并不能回答你如何解决每个请求的更一般的问题。

我建议您更改为使用UnityHierarchicalDependencyResolver,然后根据请求解析您在HierarchicalLifetimeManager中注册的任何内容。

改变这个……

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

对…

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

您遇到的问题是由运行时值与设计时依赖性混合引起的。 通常,从容器中解析的服务不应该依赖于构造函数中的运行时值。 您不应该这样做,因为组件的运行时间往往比运行时值长得多,并且将运行时值注入组件,这使得诊断和validation容器的配置变得更加困难。

相反,将该值隐藏在可以在需要时为消费者提供该实例的服务之后。 例如:

 public interface IHeaderValueProvider { HeaderValue GetCurrentValue(); } 

您可以创建一个可以轻松注册并注入任何需要该值的组件的实现。 在构造阶段之后的任何时候,这些组件都可以在注入的IHeaderValueProvider依赖项上调用GetCurrentValue()方法。

我设法通过在WebApiConfig类中声明我的自定义UnityResolver类来解决每个请求。 UnityResolver类使用HttpConfiguration类,假设您正在使用OWIN上下文。

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

ConfigureContainer类只是一个我声明我的IOC依赖项的类,如下所示:

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

使用HierarchicalLifetimeManager生命周期管理器非常重要,这样您就可以获得每个请求的新实例。

然后UnityResolver类看起来像这样:

 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(); } } 

我希望这有帮助。

有关更多信息,请访问: http : //www.asp.net/web-api/overview/advanced/dependency-injection