我试图了解 AddSingleton
、AddScoped
和 AddTransient
之间的区别。有很多解释,但我看不懂,因为我不明白什么时候HTTP请求在同一个范围内
最佳答案
因此,在 AppDomain 或正在运行的进程中,始终存在一个由所有使用者共享的“根容器”。然后为每个 HTTP 请求创建子容器(在 ASP.NET Core 中,为每个包含 HttpRequest
和 HttpResponse
的 HttpContext
)。 (请注意,也可以出于其他原因创建子容器,但这不在本答案的关注范围之内)。
Singleton
服务仅构造一次,通常仅由根容器构造。它们就像 OOP 中的单例模式(其中一个类只能实例化一次),除了在这种情况下您仍然可以手动创建多个实例,但 DI 容器本身只会创建 1 个实例。- 您可以通过从服务工厂方法返回 OOP 单例实例来将 OOP 单例与 DI 容器一起使用。
Transient
服务总是在被请求时创建 - 它们注定是短期服务。一些容器会对其创建的所有 transient 服务调用IDisposable.Dispose
,而其他容器则不会(因为它们希望消费者处置它们,请检查您的容器的政策)。请求范围的服务可以由不同的容器系统以不同的方式实现 - 但我看到的一种常见方法是在每个 HTTP 请求开始时(当创建一个新的
HttpContext
时) child-container 被创建(子容器继承其父容器的注册),然后它创建的所有对象(通常作为单例,但仅在该子容器中)然后被释放(如果适用) 当 HTTP 请求结束时(当HttpContext
被销毁时,在 HTTP 响应已发送到客户端并且响应结束后)。
完全忽略 ASP.NET - 让我们假设我们有自己的 HTTP 服务器程序和它自己的 DI 容器:
public class HttpServer
{
private readonly IContainer rootContainer;
public HttpServer()
{
this.rootContainer = RegisterServices( new ContainerBuilder() ).Build();
}
private static IContainerBuilder RegisterServices( IContainerBuilder services )
{
return services
.RegisterSingleton<ISystemClock,BiosClock>()
.RegisterSingleton<MySingleton>( factory: () => MySingleton.Instance )
.RegisterTransient<IDbConnection>( factory: () => new SqlConnection() )
.RegisterRequest<RequestTracingService>();
}
public void OnHttpRequest( Socket socket )
{
HttpContext context = new HttpContext();
context.RequestContainer = this.rootContainer.CreateChildContainer();
try
{
// hand-off the `context` object to code that reads the request, does processing, and then writes the response
}
finally
{
context.RequestContainer.Dispose(); // <-- this disposes of any objects created by RequestContainer during the processing of the request, without touching any objects created by `rootContainer`.
}
}
}
关于c# - 对于 AddScoped(), "within the same HTTP request"是什么意思,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57350302/