【问题标题】:How do I NOT use DependencyResolver.Current.GetService(...) in this situation在这种情况下如何不使用 DependencyResolver.Current.GetService(...)
【发布时间】:2014-07-06 23:10:19
【问题描述】:

按照我在这个帖子中给出的建议 [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 作为我的依赖注入框架。任何建议表示赞赏。

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

【问题讨论】:

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


    【解决方案1】:

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

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

    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()
        {
            // ...
        }
    }
    

    【讨论】:

    • 哦,看起来很可爱,谢谢。我会试一试并提供反馈。
    • 这是一种享受,看起来又漂亮又整洁。谢谢
    【解决方案2】:

    按照 Steven 的建议,最终的代码是:

    一个新的接口“IPostAuthenticateRequestProvider”

    /// <summary>
    /// Defines the expected members of a PostAuthenticateRequestProvider
    /// </summary>
    internal interface IPostAuthenticateRequestProvider
    {
        /// <summary>
        /// Applies a correctly setup principle to the Http request
        /// </summary>
        /// <param name="httpContext"></param>
        void ApplyPrincipleToHttpRequest(HttpContext httpContext);
    }
    

    实现“IPostAuthenticateRequestProvider”的具体类

    /// <summary>
    /// Provides PostAuthenticateRequest functionality
    /// </summary>
    public class MvcPostAuthenticateRequestProvider : IPostAuthenticateRequestProvider
    {
        #region Declarations
    
        private readonly IApplicationConfiguration _configuration;
    
        #endregion
    
        #region Constructors
    
        public MvcPostAuthenticateRequestProvider(IApplicationConfiguration configuration)
        {
            _configuration = configuration;
        }
    
        #endregion
    
        #region IPostAuthenticateRequestProvider Members
    
        /// <summary>
        /// Applies a correctly setup principle to the Http request
        /// </summary>
        /// <param name="httpContext"></param>
        public void ApplyPrincipleToHttpRequest(HttpContext httpContext)
        {
            // declare a collection to hold roles for the current user
            String[] roles;
    
            // Get the current identity
            var identity = HttpContext.Current.User.Identity;
    
            // Check if the request is authenticated...
            if (httpContext.Request.IsAuthenticated)
            {
                // ...it is so load the roles collection for the user
                roles = Roles.GetRolesForUser(identity.Name);
            }
            else
            { 
                // ...it isn't so load the collection with the unknown role
                roles = new[] { _configuration.UnknownUserRoleName };
            }
    
            // Create a new WebIdenty from the current identity 
            // and using the roles collection just populated
            var webIdentity = new WebIdentity(identity, roles);
    
            // Create a principal using the web identity and load it
            // with the app configuration
            var principal = new WebsitePrincipal(webIdentity)
            {
                ApplicationConfiguration = _configuration
            };
    
            // Set the user for the specified Http context
            httpContext.User = principal;
        }
    
        #endregion
    }
    

    并且在 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)
        {
            // Get a PostAuthenticateRequestProvider and use this to apply a 
            // correctly configured principal to the current http request
            var provider = (IPostAuthenticateRequestProvider)
                DependencyResolver.Current.GetService(typeof(IPostAuthenticateRequestProvider));
            provider.ApplyPrincipleToHttpRequest(HttpContext.Current);
        }
    .
    .
    }
    

    【讨论】:

      猜你喜欢
      • 2022-01-23
      • 2015-11-30
      • 2017-05-16
      • 2012-10-06
      • 2011-05-18
      • 2019-11-29
      • 2022-01-23
      • 2018-05-20
      • 2013-02-25
      相关资源
      最近更新 更多