在普通的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);
我们创建的ApiTestController
类似于TestController
,继承自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有关。
由于
答案 0 :(得分: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
最“正确”的实现,但到目前为止似乎有效。
如果没有其他人有更好的答案,我会在几天内将此标记为答案。
答案 1 :(得分:1)
不幸的是,当您调用GlobalConfiguration.Configuration.DependencyResolver.GetService时,它会完全忽略任何作用域并使用外部非子容器进行解析,该容器在应用程序的生命周期内存在。这是Web Api的一个问题,因此无法对控制器之外的每个请求依赖项使用构造函数注入。令人困惑的是,这与MVC完全不同,就像你说的那样。
您可以使用HttpRequestMessage的GetDependencyScope()扩展方法。当您将HierarchicalLifetimeManager与Unity.WebApi结合使用时,使用此功能解决的任何问题都将在每个请求范围内。该请求可以从操作过滤器和处理程序获得,因此可能是一种可行的解决方法。
显然这是纯服务位置而不是依赖注入,这远非理想,但我还没有找到另一种方法来访问控制器之外的每个请求依赖项。
有关详细信息,请参阅this post。
答案 2 :(得分:0)
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
如果你想做得对,你应该看看它们。