Registration methods¶
What you’ll learn¶
Register providers using
add(),add_instance(), and factory variants.Pick the registration method that matches a single responsibility.
Add¶
Run locally¶
uv run python examples/ex_02_registration_methods/01_add.py
"""Focused example: ``add`` for constructor-based creation."""
from __future__ import annotations
from dataclasses import dataclass
from diwire import Container
class Dependency:
pass
@dataclass(slots=True)
class Service:
dependency: Dependency
def main() -> None:
container = Container()
container.add(Dependency, provides=Dependency)
container.add(Service, provides=Service)
resolved = container.resolve(Service)
print(
f"concrete_injected_dep={isinstance(resolved.dependency, Dependency)}",
) # => concrete_injected_dep=True
if __name__ == "__main__":
main()
Add instance¶
Run locally¶
uv run python examples/ex_02_registration_methods/02_add_instance.py
"""Focused example: ``add_instance`` for pre-built objects."""
from __future__ import annotations
from dataclasses import dataclass
from diwire import Container
@dataclass(slots=True)
class Config:
value: str
def main() -> None:
container = Container()
config = Config(value="singleton")
container.add_instance(config, provides=Config)
first = container.resolve(Config)
second = container.resolve(Config)
print(f"instance_singleton={first is second}") # => instance_singleton=True
if __name__ == "__main__":
main()
Add factory¶
Run locally¶
uv run python examples/ex_02_registration_methods/03_add_factory.py
"""Focused example: ``add_factory`` for custom build logic."""
from __future__ import annotations
from dataclasses import dataclass
from diwire import Container, Lifetime
@dataclass(slots=True)
class Service:
value: str
def main() -> None:
container = Container()
build_state = {"count": 0}
def build_service() -> Service:
build_state["count"] += 1
return Service(value=f"built-{build_state['count']}")
container.add_factory(
build_service,
provides=Service,
lifetime=Lifetime.TRANSIENT,
)
first = container.resolve(Service)
second = container.resolve(Service)
print(f"factory_custom_logic={first.value}") # => factory_custom_logic=built-1
print(f"factory_is_transient={first is not second}") # => factory_is_transient=True
if __name__ == "__main__":
main()
Add generator cleanup¶
Run locally¶
uv run python examples/ex_02_registration_methods/04_add_generator_cleanup.py
"""Focused example: ``add_generator`` cleanup on scope exit."""
from __future__ import annotations
from collections.abc import Generator
from diwire import Container, Lifetime, Scope
class Resource:
pass
def main() -> None:
container = Container()
state = {"cleaned": False}
def provide_resource() -> Generator[Resource, None, None]:
try:
yield Resource()
finally:
state["cleaned"] = True
container.add_generator(
provide_resource,
provides=Resource,
scope=Scope.REQUEST,
lifetime=Lifetime.SCOPED,
)
with container.enter_scope() as request_scope:
_ = request_scope.resolve(Resource)
print(f"generator_cleaned={state['cleaned']}") # => generator_cleaned=True
if __name__ == "__main__":
main()
Add context manager cleanup¶
Run locally¶
uv run python examples/ex_02_registration_methods/05_add_context_manager_cleanup.py
"""Focused example: ``add_context_manager`` cleanup on scope exit."""
from __future__ import annotations
from collections.abc import Generator
from contextlib import contextmanager
from diwire import Container, Lifetime, Scope
class Resource:
pass
def main() -> None:
container = Container()
state = {"cleaned": False}
@contextmanager
def provide_resource() -> Generator[Resource, None, None]:
try:
yield Resource()
finally:
state["cleaned"] = True
container.add_context_manager(
provide_resource,
provides=Resource,
scope=Scope.REQUEST,
lifetime=Lifetime.SCOPED,
)
with container.enter_scope() as request_scope:
_ = request_scope.resolve(Resource)
print(f"context_manager_cleaned={state['cleaned']}") # => context_manager_cleaned=True
if __name__ == "__main__":
main()
Explicit dependencies¶
Run locally¶
uv run python examples/ex_02_registration_methods/06_explicit_dependencies.py
"""Focused example: explicit dependency mapping."""
from __future__ import annotations
import inspect
from dataclasses import dataclass
from diwire import Container
@dataclass(slots=True)
class UntypedDependency:
value: str
@dataclass(slots=True)
class ExplicitService:
raw_dependency: UntypedDependency
def main() -> None:
container = Container()
raw = UntypedDependency(value="raw")
container.add_instance(raw, provides=UntypedDependency)
def build_service(raw_dependency) -> ExplicitService: # type: ignore[no-untyped-def]
return ExplicitService(raw_dependency=raw_dependency)
signature = inspect.signature(build_service)
dependencies = {
UntypedDependency: signature.parameters["raw_dependency"],
}
container.add_factory(build_service, provides=ExplicitService, dependencies=dependencies)
resolved = container.resolve(ExplicitService)
print(f"explicit_deps_ok={resolved.raw_dependency is raw}") # => explicit_deps_ok=True
if __name__ == "__main__":
main()