对于AddScoped(),“在同一HTTP请求中”的含义是什么

时间:2019-08-04 21:22:24

标签: c#

我试图了解AddSingletonAddScopedAddTransient之间的区别。有很多解释,但我听不懂,因为我不理解何时HTTP请求在相同范围内

1 个答案:

答案 0 :(得分:3)

因此,总有一个“根容器”,由AppDomain或正在运行的进程中的所有使用者共享。然后,为每个HTTP请求(在ASP.NET Core中,为每个HttpContext包含HttpRequestHttpResponse)创建子容器。 (请注意,也可以出于其他原因创建子容器,但这不在此答案范围之内。)

  • Singleton服务仅被构造一次,通常仅由根容器构造。它们就像OOP中的Singleton模式(一个类只能实例化一次),除了在这种情况下,您仍然可以手动创建多个实例,但是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`.
        }
    }
}