叹气 startup.cs中的这一行:
services.AddScoped<IServiceProvider, ServiceProvider>();
破坏我的应用程序,无法调试,只是在说构建成功后停止。没有错误。没有例外。如果我将这一行注释掉,则所有内容都将再次运行,并且该应用程序将运行。
为什么会这样?我想注入IServiceProvider的原因是因为ActivatorUtilities需要它,并且我在BaseController中使用它来简化验证,例如:
public MyController(IServiceProvider serviceProvider) : base(serviceProvider) { }
[HttpPost]
public ActionResult Post(MyViewModel viewModel)
{
ValidateFor<MyValidator>(viewModel);
if (!IsValid)
{
... error stuff
}
return Ok("Success!");
}
在BaseController中
protected IserviceProvider ServiceProvider { get; set; }
public BaseController(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
}
public void ValidateFor<TValidator>(object instance) where TValidator : IValidator
{
// injected ServiceProvider here as a protected property of the base controller
var validator = ActivatorUtilities.CreateInstance<TValidator>(ServiceProvider);
var result = validator.Validate(instance);
if (result.IsValid)
{
return;
}
... process errors
}
解决方案是在控制器的上下文中以正确的方式使用IServiceProvider
。
所以代替:
var validator = ActivatorUtilities.CreateInstance<TValidator>(ServiceProvider);
完全摆脱控制器中的依赖关系,而改用它:
var validator = HttpContext.RequestServces.GetService<TValidator>();
答案 0 :(得分:1)
这可能是XY problem。
无需注入服务提供商,因为可以通过控制器的HttpContext
来访问当前请求
public BaseController() {
}
public void ValidateFor<TValidator>(object instance) where TValidator : IValidator {
// Access the service provider via the current request
var validator = HttpContext.RequestServces.GetService<TValidator>();
var result = validator.Validate(instance);
if (result.IsValid) {
return;
}
//... process errors
}
或者,通过使用[FromServices]
属性将所需的服务显式注入到操作中,可以避免整个服务定位器方法
[HttpPost]
public ActionResult Post(MyViewModel viewModel, [FromServices] MyValidator validator) {
ValidateFor(validator, viewModel);
if (!IsValid) {
//... error stuff
}
return Ok("Success!");
}
基本ValidateFor
可以重构的地方
protected void ValidateFor<TValidator>(TValidator validator, object instance)
where TValidator : IValidator {
var result = validator.Validate(instance);
if (result.IsValid) {
return;
}
//... process errors
}