# 资源管理扩展

<cite>
**本文档引用的文件**
- [UnRegisterExtension.cs](file://GFramework.Godot/extensions/UnRegisterExtension.cs)
- [IUnRegister.cs](file://GFramework.Core.Abstractions/events/IUnRegister.cs)
- [IUnRegisterList.cs](file://GFramework.Core.Abstractions/events/IUnRegisterList.cs)
- [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs)
- [UnRegisterList.cs](file://GFramework.Core/events/UnRegisterList.cs)
- [UnRegisterListExtension.cs](file://GFramework.Core/extensions/UnRegisterListExtension.cs)
- [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs)
- [EventBus.cs](file://GFramework.Core/events/EventBus.cs)
- [EasyEvents.cs](file://GFramework.Core/events/EasyEvents.cs)
- [OrEvent.cs](file://GFramework.Core/events/OrEvent.cs)
- [SignalFluentExtensions.cs](file://GFramework.Godot/extensions/signal/SignalFluentExtensions.cs)
- [UnRegisterListExtensionTests.cs](file://GFramework.Core.Tests/extensions/UnRegisterListExtensionTests.cs)
</cite>

## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖分析](#依赖分析)
7. [性能考虑](#性能考虑)
8. [故障排除指南](#故障排除指南)
9. [结论](#结论)
10. [附录](#附录)

## 简介
本文件围绕资源管理扩展展开，重点阐述 UnRegisterExtension 提供的资源清理与生命周期管理能力，包括自动资源释放、事件监听器注销、订阅关系清理以及内存泄漏防护等核心功能。文档将结合具体代码文件，说明各类资源清理方法的使用场景与调用时机，并给出最佳实践指导，帮助开发者在游戏开发中实现稳定、高性能、低泄漏的资源管理。

## 项目结构
资源管理扩展主要分布在以下模块：
- 抽象层：定义统一的注销接口与列表接口，确保跨平台一致性
- 核心实现：提供默认注销器、注销列表、事件系统与组合事件等
- 平台扩展：Godot 平台下的节点生命周期绑定扩展
- 测试：验证扩展方法的行为与边界条件

```mermaid
graph TB
subgraph "抽象层"
IUR["IUnRegister 接口"]
IURL["IUnRegisterList 接口"]
end
subgraph "核心实现"
DUR["DefaultUnRegister 实现"]
URL["UnRegisterList 列表"]
Evt["EasyEvent 事件"]
EBus["EventBus 总线"]
EAll["EasyEvents 全局管理"]
OREvt["OrEvent 组合事件"]
end
subgraph "平台扩展"
URExt["UnRegisterExtension 扩展"]
SigExt["SignalFluentExtensions 信号扩展"]
end
IUR --> DUR
IURL --> URL
EBus --> EAll
EBus --> Evt
OREvt --> IURL
URExt --> IUR
SigExt --> URExt
```

**图表来源**
- [IUnRegister.cs](file://GFramework.Core.Abstractions/events/IUnRegister.cs#L1-L12)
- [IUnRegisterList.cs](file://GFramework.Core.Abstractions/events/IUnRegisterList.cs#L1-L14)
- [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs#L1-L22)
- [UnRegisterList.cs](file://GFramework.Core/events/UnRegisterList.cs#L1-L37)
- [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs#L1-L39)
- [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L1-L55)
- [EasyEvents.cs](file://GFramework.Core/events/EasyEvents.cs#L1-L85)
- [OrEvent.cs](file://GFramework.Core/events/OrEvent.cs#L1-L57)
- [UnRegisterExtension.cs](file://GFramework.Godot/extensions/UnRegisterExtension.cs#L1-L23)
- [SignalFluentExtensions.cs](file://GFramework.Godot/extensions/signal/SignalFluentExtensions.cs#L1-L22)

**章节来源**
- [IUnRegister.cs](file://GFramework.Core.Abstractions/events/IUnRegister.cs#L1-L12)
- [IUnRegisterList.cs](file://GFramework.Core.Abstractions/events/IUnRegisterList.cs#L1-L14)
- [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs#L1-L22)
- [UnRegisterList.cs](file://GFramework.Core/events/UnRegisterList.cs#L1-L37)
- [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs#L1-L39)
- [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L1-L55)
- [EasyEvents.cs](file://GFramework.Core/events/EasyEvents.cs#L1-L85)
- [OrEvent.cs](file://GFramework.Core/events/OrEvent.cs#L1-L57)
- [UnRegisterExtension.cs](file://GFramework.Godot/extensions/UnRegisterExtension.cs#L1-L23)
- [SignalFluentExtensions.cs](file://GFramework.Godot/extensions/signal/SignalFluentExtensions.cs#L1-L22)

## 核心组件
- IUnRegister：定义统一的注销接口，要求实现 UnRegister() 方法以执行清理动作
- DefaultUnRegister：默认注销器实现，保存回调并在注销时调用并清理引用
- IUnRegisterList：统一注销列表接口，暴露可变的 IUnRegister 集合
- UnRegisterList：注销列表实现，提供批量注销与清空能力
- UnRegisterListExtension：扩展方法，提供 AddToUnregisterList 与 UnRegisterAll 的便捷调用
- EasyEvent：简单事件系统，注册回调返回 IUnRegister，支持触发与注销
- EventBus：类型化事件总线，封装 EasyEvents，提供 Send/Register/UnRegister
- OrEvent：组合事件，支持多事件“或”逻辑，内部维护注销列表
- UnRegisterExtension（Godot）：将 IUnRegister 与 Godot 节点生命周期绑定，节点退出场景树时自动注销
- SignalFluentExtensions（Godot）：为 Node 提供信号流畅 API，便于与注销机制配合

**章节来源**
- [IUnRegister.cs](file://GFramework.Core.Abstractions/events/IUnRegister.cs#L1-L12)
- [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs#L1-L22)
- [IUnRegisterList.cs](file://GFramework.Core.Abstractions/events/IUnRegisterList.cs#L1-L14)
- [UnRegisterList.cs](file://GFramework.Core/events/UnRegisterList.cs#L1-L37)
- [UnRegisterListExtension.cs](file://GFramework.Core/extensions/UnRegisterListExtension.cs#L1-L32)
- [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs#L1-L39)
- [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L1-L55)
- [OrEvent.cs](file://GFramework.Core/events/OrEvent.cs#L1-L57)
- [UnRegisterExtension.cs](file://GFramework.Godot/extensions/UnRegisterExtension.cs#L1-L23)
- [SignalFluentExtensions.cs](file://GFramework.Godot/extensions/signal/SignalFluentExtensions.cs#L1-L22)

## 架构总览
资源管理扩展通过“接口抽象 + 默认实现 + 扩展方法 + 平台绑定”的方式，形成清晰的层次化架构：
- 抽象层定义最小可用契约，保证跨平台一致性
- 核心实现提供通用能力（事件、注销、列表）
- 扩展方法提升易用性与可组合性
- 平台扩展将生命周期与平台事件对接，实现自动清理

```mermaid
classDiagram
class IUnRegister {
+UnRegister() void
}
class DefaultUnRegister {
-_mOnUnRegister : Action?
+UnRegister() void
}
class IUnRegisterList {
+UnregisterList : IList~IUnRegister~
}
class UnRegisterList {
-_unRegisterList : IUnRegister[]
+Add(unRegister : IUnRegister) void
+UnRegisterAll() void
}
class UnRegisterListExtension {
+AddToUnregisterList(self, unRegisterList) void
+UnRegisterAll(self) void
}
class EasyEvent {
-_mOnEvent : Action?
+Register(onEvent : Action) IUnRegister
+UnRegister(onEvent : Action) void
+Trigger() void
}
class EventBus {
-_mEvents : EasyEvents
+Send~T~() void
+Send~T~(e : T) void
+Register~T~(onEvent : Action~T~) IUnRegister
+UnRegister~T~(onEvent : Action~T~) void
}
class OrEvent {
-_mOnEvent : Action?
+UnregisterList : IList~IUnRegister~
+Or(event : IEvent) OrEvent
+Register(onEvent : Action) IUnRegister
+UnRegister(onEvent : Action) void
-Trigger() void
}
class UnRegisterExtension {
+UnRegisterWhenNodeExitTree(unRegister : IUnRegister, node : Node) IUnRegister
}
IUnRegister <|.. DefaultUnRegister
IUnRegisterList <|.. UnRegisterList
UnRegisterListExtension ..> IUnRegister : "管理"
UnRegisterListExtension ..> IUnRegisterList : "管理"
EventBus --> EasyEvents : "使用"
EventBus --> EasyEvent : "注册/注销"
OrEvent ..|> IUnRegisterList
UnRegisterExtension ..> IUnRegister : "绑定"
```

**图表来源**
- [IUnRegister.cs](file://GFramework.Core.Abstractions/events/IUnRegister.cs#L1-L12)
- [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs#L1-L22)
- [IUnRegisterList.cs](file://GFramework.Core.Abstractions/events/IUnRegisterList.cs#L1-L14)
- [UnRegisterList.cs](file://GFramework.Core/events/UnRegisterList.cs#L1-L37)
- [UnRegisterListExtension.cs](file://GFramework.Core/extensions/UnRegisterListExtension.cs#L1-L32)
- [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs#L1-L39)
- [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L1-L55)
- [OrEvent.cs](file://GFramework.Core/events/OrEvent.cs#L1-L57)
- [UnRegisterExtension.cs](file://GFramework.Godot/extensions/UnRegisterExtension.cs#L1-L23)

## 详细组件分析

### UnRegisterExtension（Godot 平台扩展）
- 功能概述：提供扩展方法，将 IUnRegister 与 Godot 节点生命周期绑定，节点退出场景树时自动执行注销
- 关键行为：
  - 监听节点 TreeExiting 事件
  - 在事件触发时调用 IUnRegister.UnRegister()
  - 返回原始 IUnRegister 实例，支持链式调用
- 使用场景：
  - UI 页面、场景切换、临时监听器等需要随节点销毁而自动清理的资源
- 调用时机：在注册监听器后立即调用，确保节点生命周期内始终受控

```mermaid
sequenceDiagram
participant Node as "Godot 节点"
participant Ext as "UnRegisterExtension"
participant UR as "IUnRegister"
Node->>Ext : "UnRegisterWhenNodeExitTree(UR, Node)"
Ext->>Node : "订阅 TreeExiting 事件"
Node-->>Ext : "TreeExiting 事件触发"
Ext->>UR : "调用 UnRegister()"
UR-->>Ext : "完成清理"
```

**图表来源**
- [UnRegisterExtension.cs](file://GFramework.Godot/extensions/UnRegisterExtension.cs#L17-L22)

**章节来源**
- [UnRegisterExtension.cs](file://GFramework.Godot/extensions/UnRegisterExtension.cs#L1-L23)

### DefaultUnRegister（默认注销器）
- 功能概述：保存注册的回调，在 UnRegister() 中调用并清理引用，防止重复调用
- 关键行为：
  - 保存 Action 回调
  - 执行回调并置空引用
  - 避免重复注销导致的异常
- 使用场景：事件注册返回的 IUnRegister 实例，通常由 EasyEvent/EasyEvents/EasyEventGeneric 等事件系统生成

```mermaid
flowchart TD
Start(["进入 UnRegister"]) --> Check["检查回调是否为空"]
Check --> |非空| Invoke["调用回调"]
Check --> |空| Skip["跳过执行"]
Invoke --> Clear["置空回调引用"]
Skip --> End(["结束"])
Clear --> End
```

**图表来源**
- [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs#L16-L21)

**章节来源**
- [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs#L1-L22)

### UnRegisterList 与 UnRegisterListExtension（批量注销）
- UnRegisterList：维护 IUnRegister 列表，提供 Add 与 UnRegisterAll
- UnRegisterListExtension：扩展方法，将 IUnRegister 添加到 IUnRegisterList，并提供 UnRegisterAll 批量清理
- 关键行为：
  - AddToUnregisterList：将单个注销项加入列表
  - UnRegisterAll：遍历列表逐一调用 UnRegister 并清空集合
- 使用场景：组件或页面集中管理多个监听器、订阅关系、定时器等资源

```mermaid
flowchart TD
Start(["开始 UnRegisterAll"]) --> Empty{"列表为空？"}
Empty --> |是| End(["结束"])
Empty --> |否| Loop["遍历列表"]
Loop --> Call["调用每个 IUnRegister.UnRegister()"]
Call --> Clear["清空列表"]
Clear --> End
```

**图表来源**
- [UnRegisterList.cs](file://GFramework.Core/events/UnRegisterList.cs#L29-L36)
- [UnRegisterListExtension.cs](file://GFramework.Core/extensions/UnRegisterListExtension.cs#L24-L31)

**章节来源**
- [UnRegisterList.cs](file://GFramework.Core/events/UnRegisterList.cs#L1-L37)
- [UnRegisterListExtension.cs](file://GFramework.Core/extensions/UnRegisterListExtension.cs#L1-L32)
- [UnRegisterListExtensionTests.cs](file://GFramework.Core.Tests/extensions/UnRegisterListExtensionTests.cs#L1-L132)

### EasyEvent 与 EventBus（事件系统）
- EasyEvent：无参事件系统，Register 返回 IUnRegister，支持 Trigger 与 UnRegister
- EventBus：类型化事件总线，封装 EasyEvents，提供 Send/Register/UnRegister
- 关键行为：
  - Register 返回 IUnRegister，便于后续注销
  - EventBus 基于类型管理事件，避免重复创建
- 使用场景：模块间解耦通信、状态变更通知、UI 交互响应等

```mermaid
sequenceDiagram
participant Caller as "调用方"
participant EBus as "EventBus"
participant EAll as "EasyEvents"
participant Evt as "EasyEvent"
Caller->>EBus : "Register<T>(handler)"
EBus->>EAll : "GetOrAddEvent<Event<T>>()"
EAll-->>EBus : "返回 Event<T>"
EBus->>Evt : "Register(handler)"
Evt-->>EBus : "返回 IUnRegister"
EBus-->>Caller : "返回 IUnRegister"
```

**图表来源**
- [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L41-L44)
- [EasyEvents.cs](file://GFramework.Core/events/EasyEvents.cs#L74-L84)
- [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs#L17-L21)

**章节来源**
- [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs#L1-L39)
- [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L1-L55)
- [EasyEvents.cs](file://GFramework.Core/events/EasyEvents.cs#L1-L85)

### OrEvent（组合事件）
- 功能概述：将多个事件通过“或”逻辑组合，任一事件触发即触发 OrEvent，并维护内部注销列表
- 关键行为：
  - Or：将其他事件注册到当前 OrEvent，并自动加入注销列表
  - UnRegister：取消指定处理函数并触发 UnRegisterAll
- 使用场景：多来源触发聚合、条件组合、复杂 UI 交互

**章节来源**
- [OrEvent.cs](file://GFramework.Core/events/OrEvent.cs#L1-L57)

### SignalFluentExtensions（Godot 信号扩展）
- 功能概述：为 Godot 对象提供 Signal() 流畅 API，便于与注销机制配合使用
- 使用场景：节点信号订阅与注销的链式调用

**章节来源**
- [SignalFluentExtensions.cs](file://GFramework.Godot/extensions/signal/SignalFluentExtensions.cs#L1-L22)

## 依赖分析
- 抽象接口依赖：IUnRegister 与 IUnRegisterList 是核心契约，被 DefaultUnRegister、UnRegisterList、OrEvent 等实现
- 事件系统依赖：EventBus 依赖 EasyEvents 进行事件实例管理；EasyEvent 依赖 DefaultUnRegister 生成注销令牌
- 平台扩展依赖：UnRegisterExtension 依赖 Godot 节点生命周期事件，实现自动注销
- 扩展方法依赖：UnRegisterListExtension 依赖 IUnRegister 与 IUnRegisterList，提供批量管理能力

```mermaid
graph LR
IUR["IUnRegister"] --> DUR["DefaultUnRegister"]
IURL["IUnRegisterList"] --> URL["UnRegisterList"]
IURL --> OREvt["OrEvent"]
EBus["EventBus"] --> EAll["EasyEvents"]
EBus --> Evt["EasyEvent"]
Evt --> DUR
URExt["UnRegisterExtension"] --> IUR
SigExt["SignalFluentExtensions"] --> URExt
```

**图表来源**
- [IUnRegister.cs](file://GFramework.Core.Abstractions/events/IUnRegister.cs#L1-L12)
- [IUnRegisterList.cs](file://GFramework.Core.Abstractions/events/IUnRegisterList.cs#L1-L14)
- [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs#L1-L22)
- [UnRegisterList.cs](file://GFramework.Core/events/UnRegisterList.cs#L1-L37)
- [OrEvent.cs](file://GFramework.Core/events/OrEvent.cs#L1-L57)
- [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L1-L55)
- [EasyEvents.cs](file://GFramework.Core/events/EasyEvents.cs#L1-L85)
- [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs#L1-L39)
- [UnRegisterExtension.cs](file://GFramework.Godot/extensions/UnRegisterExtension.cs#L1-L23)
- [SignalFluentExtensions.cs](file://GFramework.Godot/extensions/signal/SignalFluentExtensions.cs#L1-L22)

**章节来源**
- [IUnRegister.cs](file://GFramework.Core.Abstractions/events/IUnRegister.cs#L1-L12)
- [IUnRegisterList.cs](file://GFramework.Core.Abstractions/events/IUnRegisterList.cs#L1-L14)
- [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs#L1-L22)
- [UnRegisterList.cs](file://GFramework.Core/events/UnRegisterList.cs#L1-L37)
- [OrEvent.cs](file://GFramework.Core/events/OrEvent.cs#L1-L57)
- [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L1-L55)
- [EasyEvents.cs](file://GFramework.Core/events/EasyEvents.cs#L1-L85)
- [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs#L1-L39)
- [UnRegisterExtension.cs](file://GFramework.Godot/extensions/UnRegisterExtension.cs#L1-L23)
- [SignalFluentExtensions.cs](file://GFramework.Godot/extensions/signal/SignalFluentExtensions.cs#L1-L22)

## 性能考虑
- 事件注册与注销成本：每次注册返回 IUnRegister，建议在不需要时及时注销，避免回调链过长
- 批量注销：使用 UnRegisterAll 一次性清理，减少循环开销
- 自动清理：通过 UnRegisterWhenNodeExitTree 将清理与节点生命周期绑定，避免手动遗漏
- 内存泄漏防护：DefaultUnRegister 在注销后置空回调，防止闭包持有导致的泄漏
- 平台集成：Godot 信号与节点生命周期结合，确保场景切换时资源自动回收

[本节为通用性能指导，无需特定文件分析]

## 故障排除指南
- 注销多次导致异常：确认 DefaultUnRegister 只会调用一次回调并清理引用
- 批量注销无效：检查 UnRegisterList 是否正确添加 IUnRegister，UnRegisterAll 是否被调用
- 节点退出未清理：确认 UnRegisterWhenNodeExitTree 已在注册监听器后调用
- 组合事件未完全清理：OrEvent 的 UnRegister 会触发 UnRegisterAll，确保内部事件正确注册

**章节来源**
- [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs#L16-L21)
- [UnRegisterListExtensionTests.cs](file://GFramework.Core.Tests/extensions/UnRegisterListExtensionTests.cs#L56-L120)
- [UnRegisterExtension.cs](file://GFramework.Godot/extensions/UnRegisterExtension.cs#L17-L22)
- [OrEvent.cs](file://GFramework.Core/events/OrEvent.cs#L44-L48)

## 结论
资源管理扩展通过统一的注销接口与平台绑定，实现了事件监听器、订阅关系与节点生命周期的自动化清理，有效降低内存泄漏风险并提升性能稳定性。结合批量注销与组合事件机制，开发者可以更高效地管理复杂场景下的资源生命周期。

[本节为总结性内容，无需特定文件分析]

## 附录

### 最佳实践清单
- 事件注册后立即获取 IUnRegister，并在合适时机调用 UnRegister 或 UnRegisterAll
- 使用 UnRegisterWhenNodeExitTree 将节点相关资源与场景树生命周期绑定
- 通过 UnRegisterList 集中管理组件内的多项注销项，避免遗漏
- 组合事件 OrEvent 适合多来源聚合触发，注意内部事件的正确注册与注销
- 与 SignalFluentExtensions 配合，实现信号订阅的流畅与可维护

### 调用时机参考
- 事件注册：在组件初始化阶段完成
- 自动清理：在注册监听器后立即调用 UnRegisterWhenNodeExitTree
- 批量清理：在组件销毁或页面切换时调用 UnRegisterAll
- 组合事件：在 OrEvent 上注册处理函数后，确保内部事件已加入注销列表

[本节为概念性内容，无需特定文件分析]