Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

For AddScoped(), what is meant by "within the same HTTP request"

Tags:

c#

I am trying to understand the difference between AddSingleton, AddScoped and AddTransient. There are lots of explanations but I can't understand them because I don't understand when an HTTP request is within the same scope

like image 381
Sea_Ocean Avatar asked Oct 17 '25 06:10

Sea_Ocean


1 Answers

So, there's always a "root container" that's shared by all consumers in the AppDomain or running process. Child containers are then created for each HTTP request (in ASP.NET Core, for each HttpContext which encompasses HttpRequest and HttpResponse). (Note that child containers can be created for other reasons too, but that's outside this answer's concern).

  • Singleton services are only constructed once, usually only by the root container. They're like the Singleton-pattern in OOP (where a class can only be instantiated once), except in this case you can still manually create multiple instances, but the DI container will only ever create 1 instance itself.

    • You can use OOP Singletons with DI containers by returning the OOP singleton instance from a service factory method.
  • Transient services are always created when they're requested - they're meant to be short-lived services. Some containers will call IDisposable.Dispose on all transient services it creates, others will not (as they expect the consumer to dispose of them, check with your container's policies).

  • Request-scoped services can be implemented differently by different container systems - but a common approach I see is that at the start of each HTTP request (when a new HttpContext is created) a child-container is created (a child-container inherits the registrations of its parent) and then all of the objects it creates (often as singletons, but only in that child container) are then disposed (if applicable) when the HTTP request ends (when the HttpContext is destroyed, after the HTTP response has been sent to the client and the response ended).

Disregarding ASP.NET entirely - let's pretend we have our own HTTP server program with its own DI container:

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`.
        }
    }
}
like image 178
Dai Avatar answered Oct 24 '25 14:10

Dai



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!