“使用范围服务时,将服务注入 Invoke 或 InvokeAsync”是啥意思?

Posted

技术标签:

【中文标题】“使用范围服务时,将服务注入 Invoke 或 InvokeAsync”是啥意思?【英文标题】:What is the meaning of "When using a scoped service, inject the service into the Invoke or InvokeAsync"?“使用范围服务时,将服务注入 Invoke 或 InvokeAsync”是什么意思? 【发布时间】:2019-08-22 06:14:51 【问题描述】:

我正在阅读有关 .Net Core 中 DI 的 MS 文档。

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.2

我遇到了这条线

“警告

在中间件中使用作用域服务时,将服务注入 Invoke 或 InvokeAsync 方法。不要通过构造函数注入 注入,因为它强制服务表现得像一个单例。”

哪位大神解释一下这是什么意思?

然后,这里投票最多的答案之一是使用构造函数 DI 注入来进行作用域服务。 AddTransient, AddScoped and AddSingleton Services Differences?

【问题讨论】:

【参考方案1】:

这记录在 ASP.NET Core 中间件中:Per-request dependencies。

因为中间件是在应用启动时构建的,而不是按请求构建的,所以中间件构造函数使用的作用域生命周期服务不会在每个请求期间与其他依赖注入类型共享。如果您必须在中间件和其他类型之间共享范围服务,请将这些服务添加到 Invoke 方法的签名中。 Invoke 方法可以接受由 DI 填充的附加参数:

public class CustomMiddleware

private readonly RequestDelegate _next;

public CustomMiddleware(RequestDelegate next)

    _next = next;


// IMyScopedService is injected into Invoke
public async Task Invoke(HttpContext httpContext, IMyScopedService svc)

    svc.MyProperty = 1000;
    await _next(httpContext);


【讨论】:

【参考方案2】:

这是一件非常重要的事情。 您的中间件类只实例化一次,即它的构造函数只运行一次。 如果您的依赖项的生命周期为作用域或瞬态,则意味着它的生命周期较短。 如果您通过构造函数需要这种依赖关系,则您的中间件依赖于生命周期较短的服务。 DI 容器可以在请求完成后释放服务,让您的中间件拥有不再工作的服务。

通过在运行时在 Invoke/InvokeAsync 函数中请求它, 您可以使用瞬态和作用域依赖项。 构造函数中可能需要单例,因为它们与中间件具有相同的生命周期。

【讨论】:

我不确定这是否准确,我相信 DI 不会“释放”服务,而是删除它的引用并将对象留作垃圾收集。但是,垃圾回收不会发生,因为您的中间件仍然引用该对象 DI包含如果实现了IDisposable,我们将调用服务的Dispose函数。

以上是关于“使用范围服务时,将服务注入 Invoke 或 InvokeAsync”是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章