Asp.net 3.0 IServiceProvider无法注入

时间:2019-10-06 19:14:00

标签: c# asp.net-core dependency-injection asp.net-core-3.0

叹气 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>();

1 个答案:

答案 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
}

参考Dependency injection into controllers in ASP.NET Core