ASP.NET Core DI - 我可以使一个服务依赖于其他服务吗?

8
在我的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的方法,因为这看起来更简洁。


RequestInfo 是在什么时候创建的?它是由 HTTP 请求触发创建的吗? - weichch
3个回答

11

从 DI 容器获取 IHttpContextAccessor 服务,而不是获取 HttpContext(从启动类传递 HttpContext 没有任何意义):

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

你可以通过为RequestInfo引入一个interface来简化这个问题:

public interface IRequestInfo
{
}

public class RequestInfo
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    
    public RequestInfo(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }
}

并在 ConfigureServices 方法中:

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

糟糕!你可以在原始帖子中看到,我实际上尝试过这样做,但我在 sp.GetService<HttpContextAccessor> 中漏掉了接口名称中的 I。 - Andy
抱歉,我觉得你误解了我的评论。当我说“D'oh”时,我是在责备自己犯了一个显而易见的错误,而你指出了这个错误。我标记了你的答案为正确,并没有给它点踩。 - Andy

3
我通过参照Microsoft Docs - use HttpContext from custom components中的方法进行操作,成功地注入了HttpContext,无需在ConfigureServices中创建实例。
依赖注入容器会将IHttpContextAccessor提供给那些在构造函数中声明其为依赖项的类。
IHttpContextAccessor httpContextAccessor添加到类的构造函数中。
在ConfigureServices中添加services.AddHttpContextAccessor();

2

您只需要在需要使用它们之前注册所有依赖项,如下所示:

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

RequestInfo类中,您可以请求IHttpContextAccessor

public class RequestInfo
{
    private readonly IHttpContextAccessor _httpContext;

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接