Skip to content

Injector Scopes

There are 3 different scopes which defines ways a service/provider is instantiated.

transient_scope:

Whenever a transient scoped provider is required, a new instance of the provider is created

# main.py

from ellar.di import EllarInjector, transient_scope, injectable

injector = EllarInjector(auto_bind=False)


@injectable(scope=transient_scope)
class ATransientClass:
    pass

injector.container.register(ATransientClass)
# OR
# injector.container.register_transient(ATransientClass)

def validate_transient_scope():
    a_transient_instance_1 = injector.get(ATransientClass)
    a_transient_instance_2 = injector.get(ATransientClass)

    assert a_transient_instance_2 != a_transient_instance_1 # True


if __name__ == "__main__":
    validate_transient_scope()

singleton_scope:

A singleton scoped provider is created once throughout the lifespan of the Container instance.

For example:

# main.py

from ellar.di import EllarInjector, singleton_scope, injectable

injector = EllarInjector(auto_bind=False)
# OR

@injectable(scope=singleton_scope)
class ASingletonClass:
    pass

injector.container.register(ASingletonClass)
# OR
# injector.container.register_singleton(ASingletonClass)

def validate_singleton_scope():
    a_singleton_instance_1 = injector.get(ASingletonClass)
    a_singleton_instance_2 = injector.get(ASingletonClass)

    assert a_singleton_instance_2 == a_singleton_instance_1 # True

if __name__ == "__main__":
    validate_singleton_scope()

request_scope:

A request scoped provider is instantiated once during the scope of the request. And it's destroyed once the request is complete. It is important to note that request_scope behaves like a singleton_scope during HTTPConnection mode and behaves like a transient_scope outside HTTPConnection mode.

# main.py

import uvicorn
from ellar.di import EllarInjector, request_scope, injectable

injector = EllarInjector(auto_bind=False)


@injectable(scope=request_scope)
class ARequestScopeClass:
    pass


injector.container.register(ARequestScopeClass)


async def scoped_request(scope, receive, send):
    async with injector.create_asgi_args(scope, receive, send) as request_injector:
        request_instance_1 = request_injector.get(ARequestScopeClass)
        request_instance_2 = request_injector.get(ARequestScopeClass)
        assert request_instance_2 == request_instance_1

    request_instance_1 = injector.get(ARequestScopeClass)
    request_instance_2 = injector.get(ARequestScopeClass)

    assert request_instance_2 != request_instance_1


if __name__ == "__main__":
    uvicorn.run("main:scoped_request", port=5000, log_level="info")