我试图了解AddSingleton
,AddScoped
和AddTransient
之间的区别。有很多解释,但我听不懂,因为我不理解何时HTTP请求在相同范围内
答案 0 :(得分:3)
因此,总有一个“根容器”,由AppDomain或正在运行的进程中的所有使用者共享。然后,为每个HTTP请求(在ASP.NET Core中,为每个HttpContext
包含HttpRequest
和HttpResponse
)创建子容器。 (请注意,也可以出于其他原因创建子容器,但这不在此答案范围之内。)
Singleton
服务仅被构造一次,通常仅由根容器构造。它们就像OOP中的Singleton模式(一个类只能实例化一次),除了在这种情况下,您仍然可以手动创建多个实例,但是DI容器本身只能创建1个实例。
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`.
}
}
}