Skip to content

Dependency Injection API

The Dependency Injection API provides decorators, functions, and utilities for managing dependencies in your application.

Core Decorators

Injectable

Injectable

Injection Functions

inject()

inject

inject(token: type[T] | str, *, scope: type[AscModuleRef] | Literal['root'] = 'root') -> T
inject(token: type[T] | str, fallback: T | Any, *, scope: type[AscModuleRef] | Literal['root'] = 'root') -> T
inject(token: type[T] | str, fallback: T | Any | None = None, *, scope: type[AscModuleRef] | Literal['root'] = 'root') -> T | Any

Retrieves an instance of the specified token from the dependency injection system.

This function is particularly useful for standalone functions or scenarios where the injector is not directly accessible, allowing seamless access to dependencies.

Parameters:

Name Type Description Default
token type[T] | str

The type or name of the token to retrieve from the injector.

required
fallback T | Any | None

The value to return if the token is not found. If None and the token is not found, the function raises a RAISE_NOT_FOUND error. Defaults to None.

None
scope type[AscModuleRef] | Literal['root']

The scope to search for the token. - If "root" (default), the token is retrieved from the RootInjector. - If a specific AscModuleRef type is provided, the token is retrieved from that module's injector. Defaults to "root".

'root'

Returns:

Name Type Description
T T | Any

The instance of the specified token, or the fallback value if the token is not found and fallback is provided.

Raises:

Type Description
ScopeError

If the specified scope is invalid or inaccessible.

RuntimeError

If the specified module scope is not loaded, preventing access to its injector.

Examples:

    # Retrieve a token from the root scope
    my_service = inject(MyService)

    # Retrieve a token from a specific module scope
    my_service = inject(MyService, scope=MyModule)

    # Retrieve a token with a fallback value
    my_service = inject("MyService", fallback=default_service)
Notes
  • This function is ideal for use in standalone functions where injectors are not directly accessible, such as utility functions or handlers outside the main dependency injection context.
  • If the scope is a string, it must be "root". Any other string raises a ScopeError.
  • If the scope is an AscModuleRef type, it must be loaded, lazy-loaded modules cannot be accessed unless they are loaded. Otherwise, a RuntimeError is raised.

Inject

Inject

Inject(__token: str) -> Any
Inject(__token: type[T]) -> T
Inject(__token: str, __fallback: Any) -> Any
Inject(__token: type[T], __fallback: Any) -> T
Inject(__token: type[T] | str, __fallback: Any = Parameter.empty) -> T | Any

Provider Types

Provider module-attribute

Provider: TypeAlias = ValueProvider | StaticClassProvider | FactoryProvider | type[Any] | Any

Injector

Injector

Bases: ABC

Example Usage

Basic Injectable Service

from ascender.common import Injectable, inject

@Injectable()
class UserService:
    """Service for managing users."""

    def __init__(self, db_engine=inject()):
        self.db = db_engine

    async def find_by_id(self, user_id: str):
        return await self.db.query("SELECT * FROM users WHERE id = ?", user_id)

Using Different Provider Types

from ascender.core import AscModule, ClassProvider, ValueProvider, FactoryProvider

def create_config():
    return {"api_key": "secret", "timeout": 30}

@AscModule(
    providers=[
        # Class provider
        ClassProvider(provide=UserService, useClass=UserService),

        # Value provider
        ValueProvider(provide="API_KEY", useValue="my-api-key"),

        # Factory provider
        FactoryProvider(provide="Config", useFactory=create_config),
    ]
)
class AppModule:
    pass

Circular Dependencies

from ascender.common import Injectable, inject
from ascender.core.di import DependencyForwardRef

@Injectable()
class ServiceA:
    def __init__(self, service_b=inject()):
        # Use forward reference to resolve circular dependency
        self.service_b = DependencyForwardRef(lambda: service_b)

@Injectable()
class ServiceB:
    def __init__(self, service_a=inject()):
        self.service_a = service_a

See Also