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