简体   繁体   English

asp.net 核心 DI - 我可以让服务依赖于其他服务吗

[英]asp.net core DI - can I make a service dependent on other services

In my asp.net core 3.1 app I have a RequestInfo class that contains information about the current request, and I'd like to make an instance of RequestInfo availale to middleware and controllers by dependency injection.在我的 asp.net 核心 3.1 应用程序中,我有一个 RequestInfo class ,其中包含有关当前请求的信息,我想通过依赖注入使 RequestInfo 的实例对中间件和控制器可用。 Obviously the RequestInfo must be constructed for every request, and needs the HttpContext to construct it.显然RequestInfo必须为每个请求构造,并且需要HttpContext来构造它。 I'm registering a transient service like this:我正在注册这样的临时服务:

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

The problem is that when my factory is called, there is no HttpContext in the service provider.问题是当我的工厂被调用时,服务提供者中没有HttpContext。

I have tried addScoped , and I've also tried putting services.AddHttpContextAccessor();我试过addScoped ,我也试过把services.AddHttpContextAccessor(); in the top of my ConfigureServices and then calling sp.GetService<HttpContextAccessor>().HttpContext in the factory, but neither of those worked.在我的 ConfigureServices 顶部,然后在工厂中调用sp.GetService<HttpContextAccessor>().HttpContext ,但这些都不起作用。

So what I'm asking is, is there a way to specify that my service factory isn't called until the service provider has already injected the HttpContext.所以我要问的是,有没有办法指定在服务提供者已经注入 HttpContext 之前不调用我的服务工厂。

I realise there are other approaches: I could inject a RequestInfoFactory and then have the consumer call GetRequestInfo on that, or that I could use a middleware to construct the RequestInfo and add it into context.Items.我意识到还有其他方法:我可以注入一个 RequestInfoFactory,然后让消费者调用 GetRequestInfo,或者我可以使用中间件来构造 RequestInfo 并将其添加到 context.Items 中。 I just want to find out if there's a way to inject the RequestInfo directly because that seems cleaner to me.我只是想知道是否有办法直接注入 RequestInfo,因为这对我来说似乎更干净。

Instead of getting HttpContext , get IHtttpContextAccessor service from DI container (it does not make any sense to pass the HttpContext from the startup class):不是获取HttpContext ,而是从 DI 容器获取IHtttpContextAccessor服务(从启动类传递HttpContext没有任何意义):

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

You can alternatively simplify this problem by introducing an interface for RequestInfo :您也可以通过引入RequestInfo interface来简化此问题:

public interface IRequestInfo
{
}

public class RequestInfo
{
    private readonly IHttpContextAccessor _httpContext;

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

and in ConfigureServices method:ConfigureServices方法中:

services.AddHttpContextAccessor();
services.AddScoped<IRequestInfo, RequestInfo>();

I've got this working by following Microsoft Docs - use HttpContext from custom components to inject directly without creating the instance in ConfigureServices.我通过遵循Microsoft Docs 来完成这项工作 - 使用自定义组件中的 HttpContext直接注入,而无需在 ConfigureServices 中创建实例。

The dependency injection container supplies the IHttpContextAccessor to any classes that declare it as a dependency in their constructors.依赖注入容器将 IHttpContextAccessor 提供给在其构造函数中将其声明为依赖项的任何类。

  • Add IHttpContextAccessor httpContextAccessor to the classIHttpContextAccessor httpContextAccessor添加到 class
    constructor.构造函数。
  • Add services.AddHttpContextAccessor();添加services.AddHttpContextAccessor(); to
    ConfigureServices.配置服务。

You just need to register all the dependencies before they are needed as shown below:您只需要在需要之前注册所有依赖项,如下所示:

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

Inside the RequestInfo class you can ask for IHttpContextAccessorRequestInfo class 中,您可以要求IHttpContextAccessor

public class RequestInfo
{
    private readonly IHttpContextAccessor _httpContext;

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM