Bri*_*thy 5 c# asp.net unity-container asp.net-web-api
我正在使用Unity将一个服务实例注入我的ASP.NET Web API控制器的构造函数中.
在下面的代码中,我想根据发出的http请求注入不同的IAuthenticationService实现.
这可能吗?
public class AuthenticateController : ApiController
{
public AuthenticateController(IAuthenticationService authenticationService)
{
}
Run Code Online (Sandbox Code Playgroud)
简而言之,这是可能的,但我不推荐它,因为 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);
}
}
Run Code Online (Sandbox Code Playgroud)
提供者方法 arg 不必是字符串,它可以是一个HttpContextBase或任何具有您需要的数据的对象,以决定返回哪个实现。然后,您可以使用 unity 注册提供程序,并将其构造函数注入到您的控制器中。最后,在操作中,您使用提供程序来获取正确的身份验证服务实现。
如果你真的想避免提供者/工厂模式,老实说我不知道在 Unity 中会是什么样子。但在 SimpleInjector(另一个 IoC 库,基本上与 Unity 做同样的事情)中,它看起来像这样:
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));
}
});
Run Code Online (Sandbox Code Playgroud)
虽然上面的方法应该可以工作(并且Unity应该有类似的方法),但它只能通过使用静态对象来实现HttpContext.Current。我通常不喜欢这种方法,因为它隐藏了组合根中的知识,并且有效地做了与提供者相同的事情。但这只是我的意见,你可以自由选择。
在根组成期间:
container.Register<HttpGetAuthenticationService>();
container.Register<HttpPostAuthenticationService>();
Run Code Online (Sandbox Code Playgroud)
提供者实施:
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));
}
}
}
Run Code Online (Sandbox Code Playgroud)
...这又不是 Unity 的代码,但我希望 Unity 可以做同样的事情,即使 API 不同。我同意@Maarten 的观点,这种事情可以放在组合根中,也可以放在应用程序级提供程序中。我只是倾向于后者而不是前者,可能是因为它对我来说似乎不那么“神奇”。
| 归档时间: |
|
| 查看次数: |
1336 次 |
| 最近记录: |