【问题标题】:WebAPI: Accessing Child Container as a Service LocatorWebAPI:访问子容器作为服务定位器
【发布时间】:2012-10-20 01:43:36
【问题描述】:

在普通的 ASP.MVC 项目中,我们使用 Unity 和来自 http://unitymvc3.codeplex.com/ 的 Unity.Mvc3 包配置依赖解析器

我们在HierarchicalLifetimeManager注册了这个测试服务

container.RegisterType<ITestService, TestService>(new HierarchicalLifetimeManager());

我们将容器与 Global.asax.cs 中的 Mvc 挂钩:

System.Web.Mvc.DependencyResolver.SetResolver(new Unity.Mvc3.UnityDependencyResolver(container));

然后我们运行这个测试控制器:

public class TestController : Controller
{
    private readonly ITestService _service;
    public TestController(ITestService service)
    {
        this._service = service;
    }
    public ActionResult Test()
    {
        var locatedService = System.Web.Mvc.DependencyResolver.Current.GetService<ITestService>();
        if (_service == locatedService)
            return View("Success - Same Service");//This is always the result in an MVC controller
        else
            throw new Exception("Failure - Different Service Located");//This is never the result in an MVC controller
    }
}

但是,在这个项目中,我们添加了一些 WebAPI 控制器。

我们在 global.asax.cs 中有这个配置(现在使用http://unitywebapi.codeplex.com/。但我愿意接受建议):

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

我们创建了一个类似于TestControllerApiTestController,它继承自ApiController,而不是Controller。 但是,ApiTestController 未通过测试。我知道 System.Web.Mvc.DependencyResolver 类和 System.Web.Mvc.DependencyResolver.Current 属性是特定于 Mvc 的。但是 WebAPI 有等价物吗?

System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver.GetService 不起作用,因为System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver 实例是我配置的父容器。将 ITestService 注入构造函数的不是子控制器。

这个用户好像也有类似的问题:http://unitywebapi.codeplex.com/discussions/359413 但我觉得这可能与 ASP.NET 的 WebAPI 的关系比与 Unity 的关系更大。

谢谢

【问题讨论】:

    标签: asp.net-web-api unity-container ioc-container service-locator


    【解决方案1】:

    查看http://unitymvc3.codeplex.com/http://unitywebapi.codeplex.com/的来源后,我创建了这个类:

    public class MyUnityDependencyResolver : Unity.Mvc3.UnityDependencyResolver, System.Web.Http.Dependencies.IDependencyResolver
    {
        public MyUnityDependencyResolver(IUnityContainer container)
            : base(container)
        {
        }
    
        public System.Web.Http.Dependencies.IDependencyScope BeginScope()
        {
            return this;
        }
    
        public void Dispose()
        {
            Unity.Mvc3.UnityDependencyResolver.DisposeOfChildContainer();
        }
    }
    

    gobal.asax.cs 中的配置:

    var myResolver = new MyUnityDependencyResolver(container);
    System.Web.Mvc.DependencyResolver.SetResolver(myResolver);
    System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = myResolver;
    

    Unity.Mvc3.UnityDependencyResolver 使用HttpContext.Current.Items 来管理子容器。 MyUnityDependencyResolver 可能不是System.Web.Http.Dependencies.IDependencyResolver 最“正确”的实现,但它似乎到目前为止有效。

    如果没有其他人有更好的答案,我会在几天后将其标记为答案。

    【讨论】:

    • 这看起来好像根本不会创建子请求,因此,使用 HierarchicalLifetimeManager 不会导致每个请求的生命周期,而是一个单例 - 因此依赖关系将在应用程序的生命周期内存在这可能不是你想要的。
    【解决方案2】:

    DependencyResolver 不是 ASP.NET WebAPI 中依赖注入的正确接缝。

    Mark Seemann 有两篇关于使用 WebAPI 进行 DI 的非常好的文章。

    Dependency Injection and Lifetime Management with ASP.NET Web API

    Dependency Injection in ASP.NET Web API with Castle Windsor

    如果你想把它做好,你应该看看它们。

    【讨论】:

    • 他没有在他的代码中使用解析器,只在基础设施中使用。尽管如此,这还是要创建一个 UoW。你必须在某个时候绑定到一个单例。这个论点只有在他使用控制器中的解析器而不是 DI 依赖项时才有效。同样取决于上下文,如果已经有一个服务层更严格地遵守 DI,这也可能没问题。
    【解决方案3】:

    不幸的是,当您调用 GlobalConfiguration.Configuration.DependencyResolver.GetService 时,它​​会完全忽略任何作用域并使用在应用程序生命周期中存在的外部非子容器进行解析。这是 Web Api 的一个问题,并且无法对控制器之外的每个请求的依赖项使用构造函数注入。令人困惑的是,正如您所说,这与 MVC 完全不同。

    您可以做的是使用 HttpRequestMessage 之外的 GetDependencyScope() 扩展方法。在将 HierarchicalLifetimeManager 与 Unity.WebApi 结合使用时,您使用此解决的任何问题都将在每个请求范围内。该请求可从操作过滤器和处理程序中获得,因此可能是一种可行的解决方法。

    显然这是纯粹的服务定位而不是依赖注入,这远非理想,但我还没有找到另一种方法来访问控制器之外的每个请求的依赖关系。

    请参阅this post 了解更多信息。

    【讨论】:

      猜你喜欢
      • 2011-02-07
      • 1970-01-01
      • 2018-06-15
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多