asp. net core DI - могу ли я сделать сервис зависимым от других сервисов - PullRequest
2 голосов
/ 05 апреля 2020

В моем приложении asp. net core 3.1 у меня есть класс RequestInfo, который содержит информацию о текущем запросе, и я хотел бы сделать экземпляр RequestInfo доступным для промежуточного программного обеспечения и контроллеров путем внедрения зависимостей. Очевидно, что RequestInfo должен быть создан для каждого запроса, и для его создания необходим HttpContext. Я регистрирую временную службу следующим образом:

services.AddTransient<RequestInfo>(sp =>
  {
    var context = sp.GetService<HttpContext>();
    return new RequestInfo(context)
  });

Проблема в том, что когда вызывается моя фабрика, в поставщике услуг нет HttpContext.

Я пытался addScoped и я также попытался поставить services.AddHttpContextAccessor(); в верхней части моего ConfigureServices и затем вызвать sp.GetService<HttpContextAccessor>().HttpContext на заводе, но ни один из них не сработал.

Так что я спрашиваю, есть ли способ указать, что моя фабрика сервисов не вызывается до тех пор, пока провайдер услуг уже не внедрил HttpContext.

Я понимаю, что есть другие подходы: я мог бы внедрить RequestInfoFactory, а затем вызвать для этого потребительский вызов GetRequestInfo или что я мог бы использовать промежуточное программное обеспечение для создания RequestInfo и добавить его в context.Items. Я просто хочу выяснить, есть ли способ внедрить RequestInfo напрямую, потому что это кажется мне чище.

Ответы [ 3 ]

6 голосов
/ 05 апреля 2020

Вместо получения HttpContext, получите IHtttpContextAccessor сервис из контейнера DI (не имеет смысла передавать HttpContext из класса запуска):

services.AddHttpContextAccessor();
services.AddTransient<RequestInfo>(sp =>
{
    var context = sp.GetService<IHttpContextAccessor>();
    return new RequestInfo(context)
});

Вы можете упростить альтернативу эта проблема, введя interface для RequestInfo:

public interface IRequestInfo
{
}

public class RequestInfo
{
    private readonly IHttpContextAccessor _httpContext;

    public RequestInfo(IHttpContextAccessor httpContext)
    {
        _httpContext = httpContext;
    }
}

и в ConfigureServices метод:

services.AddHttpContextAccessor();
services.AddScoped<IRequestInfo, RequestInfo>();
3 голосов
/ 05 апреля 2020

Я получил эту работу, следуя Документам Microsoft - используйте HttpContext из пользовательских компонентов для непосредственного внедрения без создания экземпляра в ConfigureServices.

Контейнер внедрения зависимостей предоставляет IHttpContextAccessor для любых классов, которые объявили его как зависимость в своих конструкторах.

  • Добавьте IHttpContextAccessor httpContextAccessor в конструктор класса
    .
  • Добавьте services.AddHttpContextAccessor(); в
    ConfigureServices.
1 голос
/ 05 апреля 2020

Вам просто нужно зарегистрировать все зависимости, прежде чем они понадобятся, как показано ниже:

services.AddHttpContextAccessor();
services.AddTransient<RequestInfo>();

Внутри класса RequestInfo вы можете запросить IHttpContextAccessor

public class RequestInfo
{
    private readonly IHttpContextAccessor _httpContext;

    public RequestInfo(IHttpContextAccessor httpContext)
    {
        _httpContext = httpContext;
    }
}
...