# 事件总线模式 **本文引用的文件** - [EventBus.cs](file://GFramework.Core/events/EventBus.cs) - [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs) - [EasyEventGeneric.cs](file://GFramework.Core/events/EasyEventGeneric.cs) - [EasyEvents.cs](file://GFramework.Core/events/EasyEvents.cs) - [OrEvent.cs](file://GFramework.Core/events/OrEvent.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) - [IEventBus.cs](file://GFramework.Core.Abstractions/events/IEventBus.cs) - [IEvent.cs](file://GFramework.Core.Abstractions/events/IEvent.cs) - [ArchitectureEvents.cs](file://GFramework.Core/events/ArchitectureEvents.cs) - [EventBusTests.cs](file://GFramework.Core.Tests/events/EventBusTests.cs) - [advanced-patterns.md](file://docs/tutorials/advanced-patterns.md) - [README.md(核心框架)](file://GFramework.Core/README.md) - [SettingsChangedEvent.cs](file://GFramework.Game/setting/events/SettingsChangedEvent.cs) - [SettingsSavedEvent.cs](file://GFramework.Game/setting/events/SettingsSavedEvent.cs) ## 目录 1. [引言](#引言) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖分析](#依赖分析) 7. [性能考量](#性能考量) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 引言 本教程围绕 GFramework 的事件总线模式展开,系统讲解事件总线的设计架构与实现机制,涵盖事件处理器的注册与管理、同步与异步事件处理差异、事件路由与分发策略;并结合框架内现有实现,说明事件处理器接口设计(IEventBus、IEvent)、事件订阅与取消订阅的生命周期管理,以及异常处理与错误恢复机制。最后给出游戏开发中的典型应用案例与最佳实践。 ## 项目结构 事件总线相关代码主要位于 GFramework.Core 的 events 与 extensions 子目录,并通过抽象接口定义在 Core.Abstractions 中,形成“抽象定义 + 具体实现 + 扩展工具”的分层组织: - 抽象接口层:定义事件总线与事件的契约 - 实现层:提供基于类型的事件系统与事件管理器 - 扩展层:提供注销列表与便捷扩展方法 - 测试层:验证事件总线的注册、注销与分发行为 - 文档与示例:高级模式文档与游戏设置事件示例 ```mermaid graph TB subgraph "抽象接口层" IEventBus["IEventBus.cs"] IEvent["IEvent.cs"] end subgraph "实现层" EventBus["EventBus.cs"] EasyEvents["EasyEvents.cs"] EasyEvent["EasyEvent.cs"] EasyEventGeneric["EasyEventGeneric.cs"] OrEvent["OrEvent.cs"] DefaultUnRegister["DefaultUnRegister.cs"] UnRegisterList["UnRegisterList.cs"] end subgraph "扩展层" UnRegisterListExt["UnRegisterListExtension.cs"] end subgraph "测试层" EventBusTests["EventBusTests.cs"] end subgraph "文档与示例" AdvPatterns["advanced-patterns.md"] ArchEvents["ArchitectureEvents.cs"] SettingsChanged["SettingsChangedEvent.cs"] SettingsSaved["SettingsSavedEvent.cs"] CoreReadme["README.md核心框架"] end IEventBus --> EventBus IEvent --> EasyEvent IEvent --> EasyEventGeneric EventBus --> EasyEvents EventBus --> EasyEvent EventBus --> EasyEventGeneric OrEvent --> DefaultUnRegister UnRegisterList --> DefaultUnRegister UnRegisterListExt --> UnRegisterList EventBusTests --> EventBus AdvPatterns --> EventBus SettingsChanged --> EventBus SettingsSaved --> EventBus ArchEvents --> EventBus ``` 图表来源 - [IEventBus.cs](file://GFramework.Core.Abstractions/events/IEventBus.cs#L1-L37) - [IEvent.cs](file://GFramework.Core.Abstractions/events/IEvent.cs#L1-L16) - [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) - [EasyEventGeneric.cs](file://GFramework.Core/events/EasyEventGeneric.cs#L1-L123) - [OrEvent.cs](file://GFramework.Core/events/OrEvent.cs#L1-L57) - [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs#L1-L22) - [UnRegisterList.cs](file://GFramework.Core/events/UnRegisterList.cs#L1-L37) - [UnRegisterListExtension.cs](file://GFramework.Core/extensions/UnRegisterListExtension.cs#L1-L32) - [EventBusTests.cs](file://GFramework.Core.Tests/events/EventBusTests.cs#L1-L85) - [advanced-patterns.md](file://docs/tutorials/advanced-patterns.md#L692-L882) - [ArchitectureEvents.cs](file://GFramework.Core/events/ArchitectureEvents.cs#L1-L31) - [SettingsChangedEvent.cs](file://GFramework.Game/setting/events/SettingsChangedEvent.cs#L1-L32) - [SettingsSavedEvent.cs](file://GFramework.Game/setting/events/SettingsSavedEvent.cs#L1-L31) - [README.md(核心框架)](file://GFramework.Core/README.md#L328-L337) 章节来源 - [README.md(核心框架)](file://GFramework.Core/README.md#L1-L508) ## 核心组件 - IEventBus:事件总线接口,定义 Send、Register、UnRegister 等能力 - EventBus:IEventBus 的具体实现,基于 EasyEvents 管理事件 - EasyEvents:全局事件管理器,按类型缓存事件实例,支持 Get、GetOrAdd、Add、GetEvent 等 - EasyEvent / Event / Event:事件载体,支持注册、注销、触发,内置空操作委托避免空检查 - OrEvent:事件“或”组合器,将多个事件合并为一个触发源 - DefaultUnRegister / UnRegisterList:注销器与注销列表,统一管理生命周期 - UnRegisterListExtension:扩展方法,提供 AddToUnregisterList 与 UnRegisterAll 章节来源 - [IEventBus.cs](file://GFramework.Core.Abstractions/events/IEventBus.cs#L1-L37) - [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) - [EasyEventGeneric.cs](file://GFramework.Core/events/EasyEventGeneric.cs#L1-L123) - [OrEvent.cs](file://GFramework.Core/events/OrEvent.cs#L1-L57) - [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs#L1-L22) - [UnRegisterList.cs](file://GFramework.Core/events/UnRegisterList.cs#L1-L37) - [UnRegisterListExtension.cs](file://GFramework.Core/extensions/UnRegisterListExtension.cs#L1-L32) ## 架构总览 事件总线采用“基于类型的事件系统”,通过 EventBus 将 Send、Register、UnRegister 三类操作桥接到 EasyEvents 管理的事件实例上。事件实例由 EasyEvent 或 Event 等承载,内部使用委托聚合与空操作委托实现高效触发与安全注销。 ```mermaid classDiagram class IEventBus { +Send~T~() +Send~T~(e) +Register~T~(onEvent) IUnRegister +UnRegister~T~(onEvent) } class EventBus { -_mEvents : EasyEvents +Send~T~() +Send~T~(e) +Register~T~(onEvent) IUnRegister +UnRegister~T~(onEvent) } class EasyEvents { -_mTypeEvents : Dictionary +Get~T~() T +Register~T~() +GetOrAdd~T~() T +AddEvent~T~() +GetEvent~T~() T } class IEvent { +Register(onEvent) IUnRegister } class EasyEvent { -_mOnEvent : Action +Register(onEvent) IUnRegister +UnRegister(onEvent) +Trigger() } class Event_T_ { -_mOnEvent : Action~T~ +Register(onEvent) IUnRegister +UnRegister(onEvent) +Trigger(t) } class OrEvent { -_mOnEvent : Action +Or(event) OrEvent +Register(onEvent) IUnRegister +UnRegister(onEvent) -Trigger() } class DefaultUnRegister { -_mOnUnRegister : Action +UnRegister() } class UnRegisterList { -_unRegisterList : IUnRegister[] +Add(unRegister) +UnRegisterAll() } IEventBus <|.. EventBus EventBus --> EasyEvents : "管理事件" EasyEvents --> EasyEvent : "缓存/获取" EasyEvents --> Event_T_ : "缓存/获取" OrEvent --> DefaultUnRegister : "组合注销" UnRegisterList --> DefaultUnRegister : "管理" IEvent <|.. EasyEvent IEvent <|.. Event_T_ ``` 图表来源 - [IEventBus.cs](file://GFramework.Core.Abstractions/events/IEventBus.cs#L1-L37) - [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) - [EasyEventGeneric.cs](file://GFramework.Core/events/EasyEventGeneric.cs#L1-L123) - [OrEvent.cs](file://GFramework.Core/events/OrEvent.cs#L1-L57) - [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs#L1-L22) - [UnRegisterList.cs](file://GFramework.Core/events/UnRegisterList.cs#L1-L37) - [IEvent.cs](file://GFramework.Core.Abstractions/events/IEvent.cs#L1-L16) ## 详细组件分析 ### 事件总线接口与实现(IEventBus / EventBus) - IEventBus 定义了 Send、Register、UnRegister 的契约,支持泛型事件类型与实例发送 - EventBus 将接口委托给 EasyEvents 管理的事件实例,实现类型安全的事件分发 ```mermaid sequenceDiagram participant Caller as "调用方" participant Bus as "EventBus" participant Events as "EasyEvents" participant Evt as "Event" participant Handler as "处理器" Caller->>Bus : "Register(onEvent)" Bus->>Events : "GetOrAddEvent>()" Events-->>Bus : "Event 实例" Bus->>Evt : "Register(onEvent)" Evt-->>Caller : "IUnRegister" Caller->>Bus : "Send() / Send(e)" Bus->>Events : "GetOrAddEvent>()" Bus->>Evt : "Trigger(e)" Evt-->>Handler : "onEvent(e)" ``` 图表来源 - [IEventBus.cs](file://GFramework.Core.Abstractions/events/IEventBus.cs#L1-L37) - [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L1-L55) - [EasyEvents.cs](file://GFramework.Core/events/EasyEvents.cs#L1-L85) - [EasyEventGeneric.cs](file://GFramework.Core/events/EasyEventGeneric.cs#L1-L123) 章节来源 - [IEventBus.cs](file://GFramework.Core.Abstractions/events/IEventBus.cs#L1-L37) - [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L1-L55) ### 事件管理器(EasyEvents) - 提供静态入口与实例入口,支持按类型获取或添加事件 - 内部以类型到事件实例的字典缓存,避免重复创建 - 支持注册、获取、添加、获取或添加等操作 章节来源 - [EasyEvents.cs](file://GFramework.Core/events/EasyEvents.cs#L1-L85) ### 事件载体(EasyEvent / Event / Event) - EasyEvent:无参事件,支持注册、注销、触发 - Event / Event:带参事件,显式实现 IEvent.Register(Action),允许无参订阅 - 内部使用空操作委托避免空检查,提升触发效率 章节来源 - [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs#L1-L39) - [EasyEventGeneric.cs](file://GFramework.Core/events/EasyEventGeneric.cs#L1-L123) - [IEvent.cs](file://GFramework.Core.Abstractions/events/IEvent.cs#L1-L16) ### 事件组合(OrEvent) - OrEvent 将多个事件通过“或”逻辑组合,任一事件触发即触发自身 - 通过扩展方法将子事件的注销加入自身注销列表,统一管理 章节来源 - [OrEvent.cs](file://GFramework.Core/events/OrEvent.cs#L1-L57) - [UnRegisterListExtension.cs](file://GFramework.Core/extensions/UnRegisterListExtension.cs#L1-L32) ### 注销机制(DefaultUnRegister / UnRegisterList) - DefaultUnRegister 在 UnRegister() 时执行回调并清理引用,防止重复注销 - UnRegisterList 统一收集多个注销对象,支持批量注销与清空 章节来源 - [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs#L1-L22) - [UnRegisterList.cs](file://GFramework.Core/events/UnRegisterList.cs#L1-L37) ### 同步与异步事件处理(对比与扩展) - 框架现有实现为同步事件处理(EventBus、Event、EasyEvent) - 高级模式文档展示了异步事件处理的扩展思路:分别维护同步/异步处理器集合,发布时先处理同步处理器,再并发等待异步处理器完成,并对异常进行隔离 ```mermaid flowchart TD Start(["开始发布事件"]) --> Persist["持久化事件可选"] Persist --> Split{"是否存在同步/异步处理器?"} Split --> |同步| SyncLoop["遍历同步处理器
try-catch 隔离异常"] Split --> |异步| AsyncLoop["收集异步处理器任务"] SyncLoop --> AsyncLoop AsyncLoop --> AwaitAll{"是否有异步任务?"} AwaitAll --> |是| WaitAll["Task.WhenAll 等待完成"] AwaitAll --> |否| End(["结束"]) WaitAll --> End ``` 图表来源 - [advanced-patterns.md](file://docs/tutorials/advanced-patterns.md#L739-L795) 章节来源 - [advanced-patterns.md](file://docs/tutorials/advanced-patterns.md#L692-L882) ### 事件处理器接口设计(IEventHandler / IAsyncEventHandler) - 高级模式文档定义了 IEventHandler 与 IAsyncEventHandler,用于区分同步与异步处理 - 事件总线实现中未直接暴露这些接口,但可通过扩展实现兼容 章节来源 - [advanced-patterns.md](file://docs/tutorials/advanced-patterns.md#L810-L825) ### 事件订阅与取消订阅生命周期管理 - 注册返回 IUnRegister,调用 UnRegister() 即可注销 - 使用 UnRegisterList 收集多个注销对象,可在组件销毁时统一注销 - 扩展方法 AddToUnregisterList 与 UnRegisterAll 简化管理 章节来源 - [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs#L1-L22) - [UnRegisterList.cs](file://GFramework.Core/events/UnRegisterList.cs#L1-L37) - [UnRegisterListExtension.cs](file://GFramework.Core/extensions/UnRegisterListExtension.cs#L1-L32) - [README.md(核心框架)](file://GFramework.Core/README.md#L403-L429) ### 事件路由与分发策略 - 基于类型路由:EventBus 通过 EasyEvents 按类型获取事件实例,确保同类型事件共享同一处理器集合 - 分发策略:事件触发时依次调用已注册的处理器,保持顺序一致性 - 组合事件:OrEvent 将多个事件合并,简化订阅端逻辑 章节来源 - [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) ### 异常处理与错误恢复 - 现有实现中,事件触发采用空操作委托,避免空引用导致的异常扩散 - 高级模式文档建议在异步发布时对处理器异常进行 try-catch 隔离,保证其他处理器正常执行 - 建议在业务层对关键处理器增加重试或降级策略 章节来源 - [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs#L1-L39) - [EasyEventGeneric.cs](file://GFramework.Core/events/EasyEventGeneric.cs#L1-L123) - [advanced-patterns.md](file://docs/tutorials/advanced-patterns.md#L756-L768) ### 实际游戏开发应用案例 - 玩家行为响应:通过事件系统监听输入或状态变化,触发相应处理(如移动、攻击、拾取) - 游戏状态更新:模型层状态变化通过事件通知控制器与系统,实现 UI 与逻辑同步 - UI 事件处理:UI 层通过事件与系统解耦,避免直接依赖具体实现 章节来源 - [README.md(核心框架)](file://GFramework.Core/README.md#L328-L337) ### 架构事件(ArchitectureEvents) - 提供架构生命周期相关事件结构体,便于在架构初始化、销毁阶段进行监控与处理 章节来源 - [ArchitectureEvents.cs](file://GFramework.Core/events/ArchitectureEvents.cs#L1-L31) ### 设置系统事件(Settings*Event) - SettingsChangedEvent 与 SettingsSavedEvent 展示了泛型事件在游戏设置模块中的应用,携带变更时间与类型化设置实例 章节来源 - [SettingsChangedEvent.cs](file://GFramework.Game/setting/events/SettingsChangedEvent.cs#L1-L32) - [SettingsSavedEvent.cs](file://GFramework.Game/setting/events/SettingsSavedEvent.cs#L1-L31) ## 依赖分析 事件总线模块内部依赖关系清晰,接口与实现分离,扩展方法与注销机制相互配合,形成低耦合、高内聚的事件系统。 ```mermaid graph LR IEventBus["IEventBus.cs"] --> EventBus["EventBus.cs"] EventBus --> EasyEvents["EasyEvents.cs"] EasyEvents --> EasyEvent["EasyEvent.cs"] EasyEvents --> Event_T_["EasyEventGeneric.cs"] OrEvent["OrEvent.cs"] --> DefaultUnRegister["DefaultUnRegister.cs"] UnRegisterList["UnRegisterList.cs"] --> DefaultUnRegister UnRegisterListExt["UnRegisterListExtension.cs"] --> UnRegisterList EventBusTests["EventBusTests.cs"] --> EventBus ``` 图表来源 - [IEventBus.cs](file://GFramework.Core.Abstractions/events/IEventBus.cs#L1-L37) - [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) - [EasyEventGeneric.cs](file://GFramework.Core/events/EasyEventGeneric.cs#L1-L123) - [OrEvent.cs](file://GFramework.Core/events/OrEvent.cs#L1-L57) - [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs#L1-L22) - [UnRegisterList.cs](file://GFramework.Core/events/UnRegisterList.cs#L1-L37) - [UnRegisterListExtension.cs](file://GFramework.Core/extensions/UnRegisterListExtension.cs#L1-L32) - [EventBusTests.cs](file://GFramework.Core.Tests/events/EventBusTests.cs#L1-L85) 章节来源 - [README.md(核心框架)](file://GFramework.Core/README.md#L1-L508) ## 性能考量 - 事件触发采用空操作委托,避免空引用检查开销 - 事件实例按类型缓存,减少重复创建 - 建议避免高频事件(如每帧触发),优先使用可绑定属性或批处理 - 异步处理器建议使用并发等待并在异常隔离下执行 章节来源 - [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs#L1-L39) - [EasyEventGeneric.cs](file://GFramework.Core/events/EasyEventGeneric.cs#L1-L123) - [README.md(核心框架)](file://GFramework.Core/README.md#L431-L444) - [advanced-patterns.md](file://docs/tutorials/advanced-patterns.md#L739-L795) ## 故障排查指南 - 注销未生效:确认是否正确调用 IUnRegister.UnRegister() 或通过 UnRegisterList.UnRegisterAll() 批量注销 - 事件未触发:检查事件类型是否一致、是否使用 GetOrAddEvent 获取同一实例 - 内存泄漏:确保组件销毁时统一注销,避免持有事件引用 - 异步异常:参考高级模式文档,对异步处理器异常进行隔离处理 章节来源 - [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs#L1-L22) - [UnRegisterList.cs](file://GFramework.Core/events/UnRegisterList.cs#L1-L37) - [README.md(核心框架)](file://GFramework.Core/README.md#L403-L429) - [EventBusTests.cs](file://GFramework.Core.Tests/events/EventBusTests.cs#L1-L85) ## 结论 GFramework 的事件总线通过“接口 + 实现 + 扩展”的分层设计,提供了类型安全、低耦合、易管理的事件系统。结合注销列表与扩展方法,能够有效管理生命周期;通过架构事件与游戏模块事件,进一步完善了事件在整体架构中的作用。对于需要异步处理与更强健的异常隔离场景,可参考高级模式文档进行扩展实现。 ## 附录 - 事件总线使用要点 - 使用 EventBus.Register() 订阅事件,返回 IUnRegister 以便注销 - 使用 EventBus.Send() 或 Send(e) 发布事件 - 使用 UnRegisterList 统一管理多个注销对象 - 对高频事件与异步处理器进行性能与异常优化 章节来源 - [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L1-L55) - [UnRegisterListExtension.cs](file://GFramework.Core/extensions/UnRegisterListExtension.cs#L1-L32) - [README.md(核心框架)](file://GFramework.Core/README.md#L328-L337)