[英]Cannot Inject Dependencies into ASP.NET Web API Controller using Unity
[英]How to dynamically inject service into asp.net web api controller based on http request parameter using Unity
我正在使用Unity將一個服務實例注入我的ASP.NET Web API控制器的構造函數中。
在下面的代碼中,我想根據發出的http請求注入不同的IAuthenticationService實現。
這可能嗎?
public class AuthenticateController : ApiController
{
public AuthenticateController(IAuthenticationService authenticationService)
{
}
簡短的回答是它是可能的,但我不推薦它,因為IoC容器必須靜態地使用HttpContext.Current
來完成它。 我推薦的是更像這樣的模式:
public interface IProvideAuthenticationService
{
IAuthenticationService GetService(string requestMethod);
}
public class AuthenticationServiceProvider : IProvideAuthenticationService
{
public IAuthenticationService GetService(string requestMethod)
{
switch (requestMethod)
{
case "GET":
return new HttpGetAuthenticationService();
case "POST":
return new HttpPostAuthenticationService();
default:
throw new NotSupportedException(string.Format(
"Cannot find AuthenticationService for requestMethod '{0}'",
requestMethod));
}
}
}
public class AuthenticateController : ApiController
{
private readonly IProvideAuthenticationService _authenticationServiceProvider;
public AuthenticateController(IProvideAuthenticationService authenticationServiceProvider)
{
_authenticationServiceProvider = authenticationServiceProvider;
}
[HttpGet]
public ActionResult Get()
{
IAuthenticationService authService = _authenticationServiceProvider.GetService(HttpContext.Request.HttpMethod);
}
[HttpPost]
public ActionResult Post()
{
IAuthenticationService authService = _authenticationServiceProvider.GetService(HttpContext.Request.HttpMethod);
}
}
提供者方法arg不必是一個字符串,它可以是一個HttpContextBase
或者任何具有您需要的數據的對象來決定返回哪個實現。 然后使用unity注冊提供程序,構造函數將其注入控制器。 最后,在操作中,您使用提供程序來獲取正確的身份驗證服務實現。
如果你真的想避開提供者/工廠模式,我真的不知道在Unity中會是什么樣子。 但是在SimpleInjector(另一個基本上與Unity相同的IoC庫)中,它看起來像這樣:
container.Register<IAuthenticationService>(() => {
string requestMethod = HttpContext.Current.Request.HttpMethod;
switch (requestMethod)
{
case "GET":
return new HttpGetAuthenticationService();
case "POST":
return new HttpPostAuthenticationService();
default:
throw new NotSupportedException(string.Format("Cannot find AuthenticationService for requestMethod '{0}'", requestMethod));
}
});
雖然上面應該工作(並且應該有類似的方式來使用Unity),但它只能通過使用靜態HttpContext.Current
對象來實現。 我通常不喜歡這種方法,因為它隱藏了組合根中的知識,並且有效地做了與提供者相同的事情。 但這只是我的意見,你可以自由選擇。
在根組成期間:
container.Register<HttpGetAuthenticationService>();
container.Register<HttpPostAuthenticationService>();
供應商實施:
public class AuthenticationServiceProvider : IProvideAuthenticationService
{
private readonly Container _container;
public AuthenticationServiceProvider(Container container)
{
_container = container;
}
public IAuthenticationService GetService(string requestMethod)
{
switch (requestMethod)
{
case "GET":
return _container.GetInstance<HttpGetAuthenticationService>();
case "POST":
return _container.GetInstance<HttpPostAuthenticationService>();
default:
throw new NotSupportedException(string.Format(
"Cannot find AuthenticationService for requestMethod '{0}'",
requestMethod));
}
}
}
...再次,這不是Unity的代碼,但我希望Unity可以做同樣的事情,即使API不同。 我同意@Maarten這種事情可以在組合根或應用程序級提供程序中進行。 我傾向於選擇后者而不是前者,可能是因為它對我來說似乎不太“神奇”。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.