Dependencies can be resolved in two ways:
- By provider reference - Using
container.resolve_provider(provider) - By type - Using
container.resolve(SomeType)
When resolving by type, the container looks for a provider whose bound_type matches the requested type.
By default, the bound_type is automatically inferred from the creator's return type annotation.
One of the key features of Modern-DI since 2.x version is the automatic resolution of sub dependencies through type annotations.
Modern-DI automatically analyzes the creator function or class constructor to identify its parameter types and attempts to resolve them from registered providers.
When a factory is created:
- Modern-DI parses the creator's signature to identify parameter names and types
- For each parameter with a type annotation, it searches for a registered provider that matches by parameter type.
- If a matching provider is found, it's automatically injected when the factory is resolved
- If no matching provider is found and no default value is provided, an error is raised
For union-typed parameters (e.g. dep: A | B), the first type in the union that has a registered provider is used. If you need a specific type injected, use a concrete type annotation or supply the value explicitly via kwargs.
Example:
import dataclasses
from modern_di import Group, Container, Scope, providers
@dataclasses.dataclass(kw_only=True, slots=True, frozen=True)
class DatabaseConfig:
host: str
port: int
@dataclasses.dataclass(kw_only=True, slots=True, frozen=True)
class DatabaseConnection:
config: DatabaseConfig # Automatically resolved by type
timeout: int = 30 # Uses default value
class Dependencies(Group):
db_config = providers.Factory(
creator=DatabaseConfig,
kwargs={"host": "localhost", "port": 5432}
)
db_connection = providers.Factory(
creator=DatabaseConnection
)
container = Container(groups=[Dependencies])
connection = container.resolve(DatabaseConnection)
assert isinstance(connection.config, DatabaseConfig)
assert connection.config.host == "localhost"
assert connection.timeout == 30