【问题标题】:using a Handler in Web API and having Unity resolve per request在 Web API 中使用 Handler 并让 Unity 解析每个请求
【发布时间】:2014-04-24 09:10:35
【问题描述】:

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

var container = new UnityContainer();

container.RegisterType<IFoo,Foo>(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

提前致谢。

【问题讨论】:

    标签: c# asp.net-web-api dependency-injection unity-container


    【解决方案1】:

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

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

    public interface IHeaderValueProvider
    {
        HeaderValue GetCurrentValue();
    }
    

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

    【讨论】:

      【解决方案2】:

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

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

      改变这个...

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

      到这个...

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

      【讨论】:

      • 是特定的 web-api 吗?或者它也可以从 mvc 控制器中使用?
      【解决方案3】:

      我设法通过在 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<object> GetServices(Type serviceType)
              {
                  try
                  {
                      return container.ResolveAll(serviceType);
                  }
                  catch (ResolutionFailedException)
                  {
                      return new List<object>();
                  }
              }
      
              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

      【讨论】:

      • 默认情况下,它应该是 Web API 场景中已经存在的每个请求的新实例。
      猜你喜欢
      • 2015-04-11
      • 2018-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-15
      • 2012-09-11
      • 1970-01-01
      相关资源
      最近更新 更多