在这种情况下,我如何不使用DependencyResolver.Current.GetService(…)?
本文关键字:GetService Current DependencyResolver 这种情况下 何不使 | 更新日期: 2023-09-27 18:04:11
根据我在这个线程中给出的建议[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作为我的依赖注入框架。欢迎提出建议。
EDIT:完整代码可以在这里看到:https://github.com/dibley1973/Dibware.Template.Presentation.Web
你不能阻止在Application_PostAuthenticateRequest
中调用DI容器或抽象,但这应该不是问题,因为这个Application_PostAuthenticateRequest
可以被认为是你的组合根的一部分。或者换句话说:你必须在某个地方解决它。
在您的例子中,问题是这个方法包含了大量的代码,原因是您缺少一个抽象。要解决这个问题,可以将该方法的所有逻辑提取到一个新类中,并将其隐藏在抽象之后。剩下的代码如下:
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()
{
// ...
}
}
根据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);
}
.
.
}