c# - 在这种情况下我如何不使用 DependencyResolver.Current.GetService(...)

标签 c# dependency-injection ninject anti-patterns service-locator

按照我在这个帖子中得到的建议 [ Ninject UOW pattern, new ConnectionString after user is authenticated我现在明白我不应该使用以下行...

    var applicationConfiguration =
            (IApplicationConfiguration)
                DependencyResolver.Current.GetService(typeof(IApplicationConfiguration));

...作为服务定位器是一种反模式。

但在以下过程中,我如何实例化实现“IApplicationConfiguration”的具体对象,以便我可以使用该对象获取未知用户角色名称,或使用它来分配我的原则的“ApplicationConfiguration”属性?

Global.asax

public class MvcApplication : NinjectHttpApplication
{
    /// <summary>
    /// Handles the PostAuthenticateRequest event of the Application control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
    protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
    {
        String[] roles;
        var applicationConfiguration =
            (IApplicationConfiguration)
                DependencyResolver.Current.GetService(typeof(IApplicationConfiguration));
        var identity = HttpContext.Current.User.Identity;
        if (Request.IsAuthenticated)
        {
            roles = Roles.GetRolesForUser(identity.Name);
        }
        else
        {
            roles = new[] { applicationConfiguration.UnknownUserRoleName };
        }
        var webIdentity = new WebIdentity(identity, roles);
        var principal = new WebsitePrincipal(webIdentity)
        {
            ApplicationConfiguration = applicationConfiguration
        };

        HttpContext.Current.User = principal;
    }
    .
    .
    .
}

分辨率映射代码

    public class ApplicationConfigurationContractMapping : NinjectModule
{
    public override void Load()
    {
        Bind<IApplicationConfiguration>()
            .To<ApplicationConfiguration>();
    }
}

应用配置

public class ApplicationConfiguration : IApplicationConfiguration
{
    .
    .
    .
    .
}

我使用 Ninject 作为我的依赖注入(inject)框架。任何建议表示赞赏。

编辑:完整代码可以在这里看到: https://github.com/dibley1973/Dibware.Template.Presentation.Web

最佳答案

您无法避免在 Application_PostAuthenticateRequest 中调用 DI 容器或对其进行抽象,但这应该不是问题,因为此 Application_PostAuthenticateRequest可以被认为是你的一部分 Composition Root .或者换句话说:你必须在某个地方解决它。

但是,您的问题是此方法包含大量代码,而真正的问题是您缺少抽象。要解决此问题,请将此方法的所有逻辑提取到一个新类中并将其隐藏在抽象后面。剩下的就是下面的代码:

protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
   var provider = (IPostAuthenticateRequestProvider)
       DependencyResolver.Current.GetService(typeof(IPostAuthenticateRequestProvider));

   provider.ApplyPrincipleToCurrentRequest();
}

代码可以由您的 DI 容器构建,并将具有以下签名:

public class MvcPostAuthenticateRequestProvider : IPostAuthenticateRequestProvider
{
    private readonly IApplicationConfiguration configuration;

    public MvcPostAuthenticateRequestProvider(IApplicationConfiguration configuration)
    {
        this.configuration = configuration;
    }

    public void ApplyPrincipleToCurrentRequest()
    {
        // ...
    }
}

关于c# - 在这种情况下我如何不使用 DependencyResolver.Current.GetService(...),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23730159/

相关文章:

c# - 搜索全局地址列表/书籍

dependency-injection - 使用依赖注入(inject)将 Feathers 应用程序对象传递给 TypeGraphQL

ninject - 在集成测试中使用 IMapper

c# - Ninject -> 扫描程序集以匹配接口(interface)并加载为模块

c# - 从结构访问字段

c# - 与缓存交互时的线程安全

c# - 如何在 STA 线程中运行 NUnit 测试?

javascript - Jasmine 监视 Angular 服务

c# - 使用依赖注入(inject)是否需要使用要注入(inject)的接口(interface)而不是具体类?

c# - 我如何在 Ninject 中使用装饰器声明责任链?