"""framework/bootstrap/dependency_injection.py:依赖注入容器。 本模块是编排层的依赖注入装配点,负责管理 framework 层组件的单例注册 与解析。借鉴 external_systems 的 ``infrastructure/container.py`` 组合根 概念,但采用可变注册表形态以支持启动期分散注册、请求期按需解析。 设计原则: - framework 层组件(注册中心、EventBus、熔断器等)为应用级单例,跨请求复用 - 请求级组件(被驱动适配器、管道、用例服务)由各自 factory 按请求创建,不进入容器 (如 ``create_driven_adapters(db, outbox_config, redis_client, arq_pool, execution_port)`` 与 ``InboundPipeline.create()`` / ``ControlPlanePipeline.create()`` / ``OutboundPipeline.create()``) - 容器仅负责应用级单例的注册与解析,保持职责单一 - 线程安全:所有读写操作通过 ``threading.Lock`` 串行化 """ from __future__ import annotations import threading from typing import Any from yuxi.channels.contract.errors import InternalError __all__ = [ "DependencyInjectionContainer", ] class DependencyInjectionContainer: """依赖注入容器。 管理 framework 层组件的单例注册,提供统一的依赖解析入口。 注册形态仅支持单例:由调用方在启动期直接传入已构造实例, ``resolve`` 时原样返回。未注册的接口解析失败抛出 ``InternalError``, 因为这属于装配期编程错误(漏注册),而非客户端请求的资源不存在。 线程安全:所有注册与解析操作通过同一把 ``threading.Lock`` 串行化, 保证并发场景下注册表的读写一致性。 典型用法:: container = DependencyInjectionContainer() container.registerSingleton(EventBus, InMemoryEventBus()) container.registerSingleton(PluginRegistry, PluginRegistry()) event_bus = container.resolve(EventBus) plugin_registry = container.resolve(PluginRegistry) """ def __init__(self) -> None: """初始化依赖注入容器。 创建空的单例注册表与互斥锁。 """ self._singletons: dict[type, Any] = {} self._lock = threading.Lock() def registerSingleton(self, interface: type, instance: Any) -> None: """注册单例。 将已构造的实例绑定到指定接口类型,后续 ``resolve`` 直接返回该实例。 若同一接口已注册,则覆盖原有绑定。 Args: interface: 接口类型(通常为 Protocol 或抽象基类),作为解析键。 instance: 已构造的实例,将作为单例原样返回。 """ with self._lock: self._singletons[interface] = instance def resolve(self, interface: type) -> Any: """解析依赖。 返回绑定到该接口的单例实例。若接口未注册,抛出 ``InternalError``。 Args: interface: 接口类型(通常为 Protocol 或抽象基类),作为解析键。 Returns: 绑定到该接口的单例实例。 Raises: InternalError: 该接口未注册单例(装配期漏注册,属编程错误)。 """ with self._lock: if interface not in self._singletons: raise InternalError( message=f"Dependency not registered: {interface.__name__}", ) return self._singletons[interface]