文档记录
This commit is contained in:
128
docs/requirements/p0-feature.md
Normal file
128
docs/requirements/p0-feature.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# P0-3: Feature 需求详细文档
|
||||
|
||||
## 对齐说明
|
||||
|
||||
本文档以 `docs/requirements/p0-requirements-set.md` 为准。Feature 不再自己创建根 scope;GameFlow 创建 FeatureContext 并传入 Feature。Feature 负责自身业务行为和引用清理。
|
||||
|
||||
## 目标
|
||||
|
||||
定义业务 Feature 的统一生命周期,让每个玩法、页面流或业务入口可以独立加载、进入、退出和释放。
|
||||
|
||||
## FeatureContext
|
||||
|
||||
```csharp
|
||||
public sealed class FeatureContext
|
||||
{
|
||||
public Container Scope { get; }
|
||||
public IResourceGroup Resources { get; }
|
||||
public CompositeDisposable Disposables { get; }
|
||||
public CancellationToken CancellationToken { get; }
|
||||
}
|
||||
```
|
||||
|
||||
所有权:
|
||||
|
||||
- `Scope` 由 GameFlow 创建和释放。
|
||||
- `Resources` 由 GameFlow 创建和释放。
|
||||
- `Disposables` 由 GameFlow 创建,Feature 可加入订阅,Exit/Dispose 时清理。
|
||||
- Feature 可以在 `Scope` 内注册自己的临时服务。
|
||||
|
||||
## 生命周期接口
|
||||
|
||||
```csharp
|
||||
public interface IFeature : IDisposable
|
||||
{
|
||||
Task LoadAsync(FeatureContext context);
|
||||
Task EnterAsync(FeatureContext context);
|
||||
Task ExitAsync(FeatureContext context);
|
||||
}
|
||||
```
|
||||
|
||||
阶段职责:
|
||||
|
||||
| 方法 | 职责 |
|
||||
|------|------|
|
||||
| `LoadAsync` | 加载资源、创建 ViewModel、准备运行时依赖 |
|
||||
| `EnterAsync` | 打开 UI、订阅 Data 或事件流 |
|
||||
| `ExitAsync` | 关闭 UI、取消业务订阅 |
|
||||
| `Dispose` | 清空自身引用,释放 Feature 自己创建但未交给 context 管理的对象 |
|
||||
|
||||
## 数据传递
|
||||
|
||||
规则:
|
||||
|
||||
- 跨 Feature 持久状态放在 Data 类中,并注册到全局 Container。
|
||||
- 一次性过渡参数由目标 Feature 定义。
|
||||
- Feature 不引用其他 Feature 的内部类。
|
||||
- Feature 间直接通信不进入 P0,使用 Data 或 R3 事件流。
|
||||
|
||||
## 资源与订阅
|
||||
|
||||
规则:
|
||||
|
||||
- Feature 加载资源后必须加入 `context.Resources`,或持有明确的 handle 并在 Dispose 中释放。
|
||||
- Feature 订阅必须加入 `context.Disposables` 或 ViewModel 自己的 `CompositeDisposable`。
|
||||
- `ExitAsync` 负责停止业务订阅和关闭 UI。
|
||||
- `Dispose` 必须可重复调用。
|
||||
|
||||
## FeatureBase 可选基类
|
||||
|
||||
```csharp
|
||||
public abstract class FeatureBase : IFeature
|
||||
{
|
||||
protected FeatureContext Context { get; private set; }
|
||||
|
||||
public virtual Task LoadAsync(FeatureContext context)
|
||||
{
|
||||
Context = context;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public virtual Task EnterAsync(FeatureContext context)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public virtual Task ExitAsync(FeatureContext context)
|
||||
{
|
||||
context.Disposables.Clear();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
Context = null;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 暂不做
|
||||
|
||||
- Feature 栈。
|
||||
- 并行 Feature。
|
||||
- Feature 热重载。
|
||||
- Feature 预加载。
|
||||
- Feature 过渡动画。
|
||||
- Feature 间直接调用。
|
||||
|
||||
## 验收标准
|
||||
|
||||
| # | 标准 | 通过条件 |
|
||||
|---|------|---------|
|
||||
| 1 | Load/Enter/Exit/Dispose 顺序 | GameFlow 严格按顺序调用 |
|
||||
| 2 | 使用 FeatureContext | Feature 可从 context Resolve 服务、加入资源和订阅 |
|
||||
| 3 | 资源释放 | Feature 退出后 context.Resources 已释放 |
|
||||
| 4 | 订阅释放 | Feature 退出后订阅不再触发 |
|
||||
| 5 | Dispose 幂等 | 重复 Dispose 不抛异常 |
|
||||
| 6 | Load 失败清理 | LoadAsync 中途失败后 Dispose 可清理部分状态 |
|
||||
| 7 | Feature 隔离 | Feature 不引用其他 Feature 的内部类 |
|
||||
|
||||
## 依赖关系
|
||||
|
||||
```text
|
||||
IFeature
|
||||
├── FeatureContext
|
||||
├── Container
|
||||
├── IResourceGroup
|
||||
└── R3 CompositeDisposable
|
||||
```
|
||||
Reference in New Issue
Block a user