Asp.net 3.0 IServiceProvider не может ввести - PullRequest
1 голос
/ 06 октября 2019

вздох Эта строка в файле 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 Ответ

1 голос
/ 06 октября 2019

Это может быть проблема XY .

Нет необходимости вводить поставщика услуг, поскольку к нему можно получить доступ через 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
}

Ссылка Внедрение зависимостей в контроллеры в ASP.NET Core

...