1

在正常ASP.MVC項目中,我們配置使用Unity和Unity.Mvc3包的依賴解析器從http://unitymvc3.codeplex.com/的WebAPI:訪問子容器作爲一個服務定位器

我們有一個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); 

我們已經創建了一個ApiTestController類似TestControllerApiController繼承,而不是從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有關。

感謝

回答

2

兮兮的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最「正確」的實現,但它似乎到目前爲止工作。

如果沒有其他人有更好的答案,我會在幾天內將此標記爲答案。

+0

這看起來好像它根本不會創建子請求,因此使用HierarchicalLifetimeManager不會導致每個請求的生命週期,而是一個singleton - 所以依賴關係將在應用程序的生命週期中出現,這可能不是什麼你要。 –

0

DependencyResolver不是ASP.NET WebAPI中依賴注入的正確接縫。

Mark Seemann在DI上使用WebAPI有兩篇非常好的帖子。

Dependency Injection and Lifetime Management with ASP.NET Web API

Dependency Injection in ASP.NET Web API with Castle Windsor

如果你想這樣做的權利,你應該看看他們。

+0

他沒有在代碼中使用解析器,只在基礎架構中使用解析器。儘管如此,這還是創造了一個UoW。你必須在某個時候綁定一個單身人士。只有他在控制器中使用解析器而不是DI依賴關係時,此參數纔有效。再次取決於上下文,如果已經有一個更嚴格遵守DI的服務層,這也可以。 – Alwyn

1

不幸的是,當你調用GlobalConfiguration.Configuration.DependencyResolver.GetService時,它完全忽略了任何作用域,並且在應用程序的生命週期中使用外部的非子容器來解決這個問題。這是Web Api的一個問題,並且無法使用構造器注入來控制控制器之外的每個請求依賴項。令人困惑的是,這與MVC完全不同,就像你說的那樣。

你可以做的是使用關閉HttpRequestMessage的GetDependencyScope()擴展方法。將HierarchicalLifetimeManager與Unity.WebApi結合使用時,使用此方法解決的任何問題都將在每個請求範圍內進行。該請求可從行爲過濾器和處理程序中獲得,因此可能是一種可行的解決方法。

很明顯,這是純粹的服務位置,而不是依賴注入,這遠非理想,但我還沒有找到另一種方式來訪問控制器之外的每請求依賴關係。

有關更多信息,請參閱this post