Asp.net 3.0 IServiceProvider 无法注入
Asp.net 3.0 IServiceProvider cannot inject
叹息 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>();
这可能是 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
}
引用Dependency injection into controllers in ASP.NET Core
叹息 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>();
这可能是 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
}