ASP.NET MVC 中使用城堡温莎的条件依赖解析
Conditional dependency resolution in ASP.NET MVC using castle windsor
我正在尝试在我们的代码中解决这种情况,我需要根据特定条件在运行时解决依赖关系,例如某个查询字符串值是否存在。
假设我有一个控制器 AuthenticationController 并且我有两种类型的身份验证服务。
public class AuthenticationController
{
private readonly IAuthenticationService authenticationService;
public AuthenticationController(IAuthenticationService authenticationService)
{
this.authenticationService = authenticationService;
}
public ActionResult LogOn(LogOnModel model)
{
var isAuthenticated = authenticationService.AuthenticatUser(model.UserName, model.Password);
}
}
public interface IAuthenticationService
{
bool AuthenticatUser(string userName, string password);
}
public class ProviderBasedAuthenticationService : IAuthenticationService
{
public bool AuthenticatUser(string userName, string password)
{
// Authentication using provider;
return true;
}
}
public class ThirdPartyAuthenticationService : IAuthenticationService
{
public bool AuthenticatUser(string userName, string password)
{
// Authentication using third party;
return true;
}
}
我已经使用 castle windsor 实现了 IoC 和 DI。
我正在为 Castle 容器中的 IAuthenticationService 注册 ProviderBasedAuthenticationService 和 ThirdPartyAuthenticationService。
目前 Castle 在解析 IAuthenticationService 时解析第一个注册类型的对象。
我希望根据请求 URL 或路由数据中作为查询字符串一部分的特定值来解析适当类型的 IAuthenticationService。
我发现这可以使用 Microsoft UnityContainer 以某种方式完成,但我不确定如何在 Castle Windsor 中实现。 (我现在无法将我的容器更改为 Microsoft UnityContainer)。
如果有人能帮助我解决这个问题或提供一些指导,我将不胜感激。
感谢和问候,
Chetan Ranpariya
您可以使用工厂方法来完成此操作。这是一个例子:
private WindsorContainer ContainerFactory()
{
var container = new WindsorContainer();
container.Register(
Component.For<ProviderBasedAuthenticationService>()
.LifeStyle.Transient,
Component.For<ThirdPartyAuthenticationService>()
.LifeStyle.Transient,
Component.For<AuthenticationController>()
.LifeStyle.Transient,
Component.For<IAuthenticationService>()
.UsingFactoryMethod((k, c) => this.AuthenticationServiceFactory(k)));
return container;
}
private IAuthenticationService AuthenticationServiceFactory(IKernel kernel)
{
return HttpContext.Current != null &&
HttpContext.Current.Request != null &&
HttpContext.Current.Request.QueryString["SomeKey"] != null
? (IAuthenticationService)kernel.Resolve<ThirdPartyAuthenticationService>()
: (IAuthenticationService)kernel.Resolve<ProviderBasedAuthenticationService>();
}
以及 2 个单元测试来证明解决方案
[Fact]
public void Resolve_WithoutTheRequiredQueryString_ReturnsProviderBasedAuthenticationService()
{
var container = this.ContainerFactory();
var result = container.Resolve<AuthenticationController>();
Assert.IsType<ProviderBasedAuthenticationService>(result.authenticationService);
}
[Fact]
public void Resolve_WithTheRequiredQueryString_ReturnsThirdPartyAuthenticationService()
{
var container = this.ContainerFactory();
HttpContext.Current = new HttpContext(
new HttpRequest("", "http://localhost", "SomeKey=Value"),
new HttpResponse(null));
var result = container.Resolve<AuthenticationController>();
Assert.IsType<ThirdPartyAuthenticationService>(result.authenticationService);
}
我正在尝试在我们的代码中解决这种情况,我需要根据特定条件在运行时解决依赖关系,例如某个查询字符串值是否存在。
假设我有一个控制器 AuthenticationController 并且我有两种类型的身份验证服务。
public class AuthenticationController
{
private readonly IAuthenticationService authenticationService;
public AuthenticationController(IAuthenticationService authenticationService)
{
this.authenticationService = authenticationService;
}
public ActionResult LogOn(LogOnModel model)
{
var isAuthenticated = authenticationService.AuthenticatUser(model.UserName, model.Password);
}
}
public interface IAuthenticationService
{
bool AuthenticatUser(string userName, string password);
}
public class ProviderBasedAuthenticationService : IAuthenticationService
{
public bool AuthenticatUser(string userName, string password)
{
// Authentication using provider;
return true;
}
}
public class ThirdPartyAuthenticationService : IAuthenticationService
{
public bool AuthenticatUser(string userName, string password)
{
// Authentication using third party;
return true;
}
}
我已经使用 castle windsor 实现了 IoC 和 DI。
我正在为 Castle 容器中的 IAuthenticationService 注册 ProviderBasedAuthenticationService 和 ThirdPartyAuthenticationService。
目前 Castle 在解析 IAuthenticationService 时解析第一个注册类型的对象。
我希望根据请求 URL 或路由数据中作为查询字符串一部分的特定值来解析适当类型的 IAuthenticationService。
我发现这可以使用 Microsoft UnityContainer 以某种方式完成,但我不确定如何在 Castle Windsor 中实现。 (我现在无法将我的容器更改为 Microsoft UnityContainer)。
如果有人能帮助我解决这个问题或提供一些指导,我将不胜感激。
感谢和问候, Chetan Ranpariya
您可以使用工厂方法来完成此操作。这是一个例子:
private WindsorContainer ContainerFactory()
{
var container = new WindsorContainer();
container.Register(
Component.For<ProviderBasedAuthenticationService>()
.LifeStyle.Transient,
Component.For<ThirdPartyAuthenticationService>()
.LifeStyle.Transient,
Component.For<AuthenticationController>()
.LifeStyle.Transient,
Component.For<IAuthenticationService>()
.UsingFactoryMethod((k, c) => this.AuthenticationServiceFactory(k)));
return container;
}
private IAuthenticationService AuthenticationServiceFactory(IKernel kernel)
{
return HttpContext.Current != null &&
HttpContext.Current.Request != null &&
HttpContext.Current.Request.QueryString["SomeKey"] != null
? (IAuthenticationService)kernel.Resolve<ThirdPartyAuthenticationService>()
: (IAuthenticationService)kernel.Resolve<ProviderBasedAuthenticationService>();
}
以及 2 个单元测试来证明解决方案
[Fact]
public void Resolve_WithoutTheRequiredQueryString_ReturnsProviderBasedAuthenticationService()
{
var container = this.ContainerFactory();
var result = container.Resolve<AuthenticationController>();
Assert.IsType<ProviderBasedAuthenticationService>(result.authenticationService);
}
[Fact]
public void Resolve_WithTheRequiredQueryString_ReturnsThirdPartyAuthenticationService()
{
var container = this.ContainerFactory();
HttpContext.Current = new HttpContext(
new HttpRequest("", "http://localhost", "SomeKey=Value"),
new HttpResponse(null));
var result = container.Resolve<AuthenticationController>();
Assert.IsType<ThirdPartyAuthenticationService>(result.authenticationService);
}