c# - 对于 AddScoped(),“在同一个 HTTP 请求中”是什么意思
问题描述
我试图理解 和 之间的AddSingleton
区别。有很多解释,但我无法理解,因为我不明白 HTTP 请求何时在同一范围内AddScoped
AddTransient
解决方案
因此,AppDomain 或运行进程中的所有消费者都共享一个“根容器”。然后为每个 HTTP 请求创建子容器(在 ASP.NET Core 中,每个HttpContext
包含HttpRequest
和HttpResponse
)。(请注意,也可以出于其他原因创建子容器,但这不在此答案的关注范围内)。
Singleton
服务只构建一次,通常只由根容器构建。它们就像 OOP 中的单例模式(一个类只能被实例化一次),除了在这种情况下您仍然可以手动创建多个实例,但 DI 容器本身只会创建 1 个实例。- 您可以通过从服务工厂方法返回 OOP 单例实例来将 OOP 单例与 DI 容器一起使用。
Transient
服务总是在被请求时创建——它们是短暂的服务。一些容器会调用IDisposable.Dispose
它创建的所有临时服务,而另一些则不会(因为他们希望消费者处理它们,请检查容器的策略)。请求范围的服务可以由不同的容器系统以不同的方式实现 - 但我看到的一种常见方法是在每个 HTTP 请求的开始(当创建一个新请求时
HttpContext
)创建一个子容器(一个子容器继承它的父对象),然后它创建的所有对象(通常作为单例,但仅在该子容器中)然后在 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`.
}
}
}
推荐阅读
- python - Docker 容器网络:Redis 和自定义镜像
- python - 用于从图像中获取文本的 OCR
- aspnetboilerplate - 如何在 AbpBoilerPlate 中配置我的 IErrorInfoBuilder 的注入
- pandas - 在没有循环的情况下按行计算 pandas 中的余弦相似度
- wpf - MaterialDesignInXaml TextBox 和其他 UI 元素在禁用时不可读
- javascript - 不同的html画布坐标
- java - “读者”永远不会关闭......如何解决这个问题?
- java - docx4j 创建编号和未编号列表
- symfony - Get initial value of entity in FormExtension
- java - Springboot SessionListener 函数(sessionCreated(), sessionDestroyed()) 未调用