【问题标题】:Asp.net 3.0 IServiceProvider cannot injectAsp.net 3.0 IServiceProvider 无法注入
【发布时间】:2019-10-06 19:14:00
【问题描述】:

sigh 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>();

【问题讨论】:

标签: c# asp.net-core dependency-injection asp.net-core-3.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

【讨论】:

  • 效果很好。在以前的项目 asp.net core 2.0 上,以前的范例是有效的。然而,这种将验证器直接注入控制器方法的模式也很棒。
  • 不过我会说ValidateFor&lt;TValidator&gt;(instance); 看起来确实更干净。
猜你喜欢
  • 2019-01-26
  • 1970-01-01
  • 1970-01-01
  • 2020-03-18
  • 1970-01-01
  • 1970-01-01
  • 2015-07-11
  • 2012-08-10
  • 2020-04-27
相关资源
最近更新 更多