【问题标题】:Conditional dependency resolution in ASP.NET MVC using castle windsorASP.NET MVC 中使用城堡温莎的条件依赖解析
【发布时间】:2015-08-18 06:48:16
【问题描述】:

我试图在我们的代码中解决这种情况,我需要根据特定条件在运行时解决依赖关系,例如是否存在某个查询字符串值。

假设我有一个控制器 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;
    }
}

我已经使用城堡温莎实现了 IoC 和 DI。

我正在 Castle 容器中为 IAuthenticationService 注册 ProviderBasedAuthenticationService 和 ThirdPartyAuthenticationService。

目前 Castle 在解析 IAuthenticationService 时会解析第一个注册类型的对象。

我希望根据请求 URL 或路由数据中查询字符串中的某些值来解析适当类型的 IAuthenticationService。

我发现这可以使用 Microsoft UnityContainer 以某种方式完成,但我不确定如何在 Castle Windsor 中实现这一点。 (我现在无法将容器更改为 Microsoft UnityContainer)。

如果有人能在这方面帮助我或提供一些指导,我们将不胜感激。

感谢和问候, 切坦兰帕里亚

【问题讨论】:

    标签: asp.net-mvc dependency-injection inversion-of-control castle-windsor


    【解决方案1】:

    您可以使用工厂方法来做到这一点。这是一个例子:

    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);
    }
    

    【讨论】:

    • 嗨,qujk,你成功了。我有些想不出有单独的工厂方法,但我试图使用内联动态方法来做到这一点。您提供的方法肯定会奏效。谢谢你。 - Chetan Ranpariya
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多