Как я НЕ пользователь DependencyResolver.Current.GetService(...) в этой ситуации/

Следуя советам, которые мне дали в этой теме [шаблон Ninject UOW, новый ConnectionString после аутентификации пользователя Теперь я понимаю, что я не должен использовать следующую строку...

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

ApplicationConfiguration

public class ApplicationConfiguration : IApplicationConfiguration
{
    .
    .
    .
    .
}

Я использую Ninject как свою инфраструктуру Injection Dependency. Любые предложения оценили.

EDIT: Полный код можно увидеть здесь: https://github.com/dibley1973/Dibware.Template.Presentation.Web

Ответ 1

Вы не можете запретить называть либо фреймворк DI, либо абстракцию над ним в вашем Application_PostAuthenticateRequest, но это не должно быть проблемой, так как этот Application_PostAuthenticateRequest можно считать частью вашего Корень композиции. Или другими словами: вы должны где-то решить.

Однако проблема в вашем случае заключается в том, что этот метод содержит очень много кода, и реальная проблема заключается в том, что здесь отсутствует абстракция. Чтобы решить эту проблему, извлеките всю логику этого метода в новый класс и спрячьте его за абстракцией. Остается следующий код:

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

   provider.ApplyPrincipleToCurrentRequest();
}

Код может быть создан вашим контейнером и будет иметь следующую подпись:

public class MvcPostAuthenticateRequestProvider : IPostAuthenticateRequestProvider
{
    private readonly IApplicationConfiguration configuration;

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

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

Ответ 2

Следуя предложению Стивена, последний код:

Новый интерфейс "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);
    }
.
.
}