Files
FlowScope/docs/requirements/p0-container.md
2026-05-15 15:38:40 +08:00

4.4 KiB
Raw Blame History

P0-1: Container 需求详细文档

对齐说明

本文档以 docs/requirements/p0-requirements-set.md 为准。P0 允许 DI 自动注入进入首版,但必须保持 Container 核心轻量核心只负责注册、解析、作用域和释放Source Generator 与运行时反射只是生成工厂函数的适配层。

目标

提供 Game Core 的基础依赖容器支持显式工厂注册、Attribute + Source Generator 自动注入、Attribute + 运行时反射降级、子作用域和可预测释放。

P0 功能需求

1. 显式注册

public sealed class Container : IDisposable
{
    public void RegisterInstance<T>(T instance);
    public void RegisterFactory<T>(Func<Container, T> factory);
    public T Resolve<T>();
    public bool TryResolve<T>(out T value);
    public Container CreateScope();
    public void Dispose();
}

规则:

  • RegisterInstance<T> 注册外部实例Container 不负责释放。
  • RegisterFactory<T> 首次 Resolve 时创建实例,后续返回同一实例。
  • 工厂创建且实现 IDisposable 的实例由当前 scope 释放。
  • 子 scope 可访问父 scope 注册。
  • 子 scope 可覆盖父 scope 注册,且不污染父 scope。
  • 已 Dispose 的 scope 调用 Register/Resolve 必须抛 ObjectDisposedException

2. Attribute 自动注入

[AttributeUsage(AttributeTargets.Class)]
public sealed class InjectableAttribute : Attribute
{
}
public sealed class Container : IDisposable
{
    public void RegisterType<TInterface, TImplementation>()
        where TImplementation : TInterface;

    public void RegisterType<TImplementation>();
    public void RegisterAssembly();
}

规则:

  • 自动注入只支持构造函数注入。
  • 只允许一个 public 构造函数。
  • 构造函数参数从当前 Container 递归 Resolve。
  • 循环依赖必须检测,并输出完整依赖链。
  • [Inject] 属性注入和方法注入不进入 P0。

3. Source Generator 推荐路径

Source Generator 是 P0 推荐自动注入路径。

要求:

  • 编译期扫描 [Injectable] 类型。
  • 为每个 Injectable 类型生成等价于手写工厂的静态工厂方法。
  • 编译期检查构造函数依赖是否可解析,无法确认时发出诊断。
  • Generator 程序集与 Runtime 程序集分离。
  • 未启用 Source Generator 时,显式工厂模式仍可独立使用。

4. 运行时反射降级路径

运行时反射是 P0 可选降级路径。

要求:

  • 仅在启用反射模式时使用。
  • 反射只在首次 Resolve 时构造并缓存结果。
  • 行为必须与 Source Generator 模式一致。
  • IL2CPP/AOT 风险需要在文档中明确提示。

5. 释放规则

  • 当前 scope Dispose 时按创建逆序释放本 scope 管理的 IDisposable
  • 父 scope Dispose 时,先释放未释放的子 scope。
  • Dispose() 可重复调用,后续调用静默忽略。
  • 某个实例 Dispose 抛异常时,记录错误并继续释放其余实例。

暂不做

  • [Inject] 属性注入。
  • [Inject] 方法注入。
  • Transient / Scoped / Singleton 多生命周期模式。
  • 开放泛型注册。
  • 装饰器注册。
  • 条件注册。
  • 运行时动态切换 DI 模式。

验收标准

# 标准 通过条件
1 显式实例注册 RegisterInstanceResolve 返回同一实例
2 显式工厂注册 RegisterFactory 首次 Resolve 创建实例,后续复用
3 Source Generator 自动注入 [Injectable] 类型可通过 RegisterType 正常解析
4 运行时反射自动注入 反射模式下行为与 Source Generator 一致
5 递归解析 A 依赖 B、B 依赖 C 时 Resolve A 可自动解析整条链
6 循环依赖检测 A -> B -> A 抛异常,错误包含依赖链
7 子 scope 读取父级 子 scope 可 Resolve 父 scope 注册
8 子 scope 覆盖父级 子 scope 覆盖后父 scope 不受影响
9 逆序释放 多个工厂实例按创建逆序 Dispose
10 外部实例不释放 RegisterInstance 传入的实例不由 Container Dispose
11 重复 Dispose 第二次 Dispose 不重复释放、不抛异常
12 已释放 scope 防护 已 Dispose scope 调用 Register/Resolve 抛 ObjectDisposedException

依赖关系

Container Runtime
├── 纯 C#,不依赖 Unity API
├── 不依赖 R3
├── Source Generator 适配层依赖 Roslyn
└── Reflection 适配层依赖 System.Reflection