diff --git a/GFramework.Core.Godot/GFramework.Core.Godot.csproj b/GFramework.Core.Godot/GFramework.Core.Godot.csproj
index 9526647..26631d2 100644
--- a/GFramework.Core.Godot/GFramework.Core.Godot.csproj
+++ b/GFramework.Core.Godot/GFramework.Core.Godot.csproj
@@ -9,15 +9,16 @@
-
+
+
-
+
-
+
diff --git a/GFramework.Core.Godot/component/DragDropComponent.cs b/GFramework.Core.Godot/component/DragDropComponent.cs
new file mode 100644
index 0000000..c637820
--- /dev/null
+++ b/GFramework.Core.Godot/component/DragDropComponent.cs
@@ -0,0 +1,181 @@
+using GFramework.Core.architecture;
+using GFramework.Core.controller;
+using GFramework.Core.events;
+using GFramework.Core.extensions;
+using GFramework.Core.Godot.extensions;
+using Godot;
+
+namespace GFramework.Core.Godot.component;
+
+///
+/// 拖拽组件类,用于处理节点的拖放逻辑。
+/// 实现了 IController 接口以支持架构通信,并通过信号通知拖拽事件的发生。
+///
+public abstract partial class DragDropComponent : Node, IController
+{
+ ///
+ /// 当拖拽被取消时触发的信号。
+ ///
+ /// 拖拽起始位置。
+ [Signal]
+ public delegate void DragCanceledEventHandler(Vector2 startingPosition);
+
+ ///
+ /// 当拖拽开始时触发的信号。
+ ///
+ [Signal]
+ public delegate void DragStartedEventHandler();
+
+ ///
+ /// 当拖拽结束并放置时触发的信号。
+ ///
+ /// 拖拽起始位置。
+ [Signal]
+ public delegate void DroppedEventHandler(Vector2 startingPosition);
+
+ ///
+ /// 取消注册列表,用于管理需要在节点销毁时取消注册的对象
+ ///
+ private readonly IUnRegisterList _unRegisterList = new UnRegisterList();
+
+ private bool _isDragging;
+ private Vector2 _offset = Vector2.Zero;
+
+ private Vector2 _startingPosition;
+
+ ///
+ /// 目标区域,通常是可交互的游戏对象(如单位或物品)所在的碰撞区域。
+ ///
+ public required Area2D Target { get; set; }
+
+ ///
+ /// 是否启用拖拽功能。若为 false,则忽略所有输入事件。
+ ///
+ public bool Enable { get; set; }
+
+ public string GroupName { get; set; } = "dragging";
+
+ public int ZIndexMax { get; set; } = 99;
+ public int ZIndexMin { get; set; } = 0;
+
+ ///
+ /// 获取游戏架构实例
+ ///
+ /// 返回游戏架构接口实例
+ public abstract IArchitecture GetArchitecture();
+
+ ///
+ /// 节点准备就绪时的回调方法。
+ /// 在节点添加到场景树后调用,绑定目标区域的输入事件处理器。
+ ///
+ public override void _Ready()
+ {
+ Target = GetParent() as Area2D ?? throw new InvalidOperationException("Target must be an Area2D node.");
+ Target.InputEvent += OnTargetInputEvent;
+ }
+
+ ///
+ /// 处理输入事件的方法
+ ///
+ /// 输入事件对象
+ public override void _Input(InputEvent @event)
+ {
+ // 处理取消拖拽操作:当正在拖拽且按下取消拖拽按键时,执行取消拖拽逻辑
+ if (!_isDragging || Target.IsInvalidNode() || !@event.IsActionPressed("cancel_drag")) return;
+ CancelDragging();
+ // 设置输入为处理,防止输入穿透
+ this.SetInputAsHandled();
+ }
+
+ ///
+ /// 处理目标区域接收到的输入事件。
+ /// 根据当前是否处于拖拽状态以及用户操作决定执行开始、取消或完成拖拽的动作。
+ ///
+ /// 接收输入事件的视图端口节点。
+ /// 发生的输入事件。
+ /// 事件索引(未使用)。
+ private void OnTargetInputEvent(Node viewport, InputEvent @event, long _)
+ {
+ if (!Enable) return;
+
+ // 获取当前正在拖拽的对象
+ var draggingObj = GetTree().GetFirstNodeInGroup(GroupName);
+ switch (_isDragging)
+ {
+ // 如果当前没有拖拽操作且已有其他对象正在拖拽,则直接返回
+ case false when draggingObj is not null:
+ return;
+ // 处理开始拖拽操作:当未在拖拽状态且按下选择按键时,开始拖拽
+ case false when @event.IsActionPressed("select"):
+ StartDragging();
+ break;
+ // 处理放置操作:当正在拖拽且释放选择按键时,执行放置逻辑
+ case true when @event.IsActionReleased("select"):
+ Drop();
+ break;
+ }
+ }
+
+ ///
+ /// 每帧更新逻辑,在拖拽过程中持续更新目标的位置。
+ ///
+ /// 与上一帧的时间间隔(秒)。
+ public override void _Process(double delta)
+ {
+ if (_isDragging && Target.IsValidNode()) Target.GlobalPosition = Target.GetGlobalMousePosition() + _offset;
+ }
+
+ ///
+ /// 结束拖拽流程的基础方法。
+ /// 清除拖拽标志位并将目标从拖拽组中移除,恢复其层级顺序。
+ ///
+ private void EndDragging()
+ {
+ _isDragging = false;
+ Target.RemoveFromGroup(GroupName);
+ Target.ZIndex = ZIndexMin;
+ }
+
+ ///
+ /// 执行取消拖拽的操作。
+ /// 调用 EndDragging 并发出 DragCanceled 信号。
+ ///
+ private void CancelDragging()
+ {
+ EndDragging();
+ EmitSignalDragCanceled(_startingPosition);
+ }
+
+ ///
+ /// 开始拖拽操作。
+ /// 设置初始位置和偏移量,将目标加入拖拽组并提升显示层级,最后发出 DragStarted 信号。
+ ///
+ private void StartDragging()
+ {
+ _isDragging = true;
+ _startingPosition = Target.GlobalPosition;
+ Target.AddToGroup(GroupName);
+ Target.ZIndex = ZIndexMax;
+ _offset = Target.GlobalPosition - Target.GetGlobalMousePosition();
+ EmitSignalDragStarted();
+ }
+
+ ///
+ /// 完成一次拖拽操作。
+ /// 调用 EndDragging 方法并发出 Dropped 信号。
+ ///
+ private void Drop()
+ {
+ EndDragging();
+ EmitSignalDropped(_startingPosition);
+ }
+
+ ///
+ /// 节点退出场景树时的回调方法。
+ /// 在节点从场景树移除前调用,用于清理资源。
+ ///
+ public override void _ExitTree()
+ {
+ _unRegisterList.UnRegisterAll();
+ }
+}
\ No newline at end of file
diff --git a/GFramework.Core.Godot/extensions/NodeExtensions.cs b/GFramework.Core.Godot/extensions/NodeExtensions.cs
index 5b5522d..d124e29 100644
--- a/GFramework.Core.Godot/extensions/NodeExtensions.cs
+++ b/GFramework.Core.Godot/extensions/NodeExtensions.cs
@@ -1,87 +1,64 @@
-using System;
-using System.Threading.Tasks;
-using Godot;
+using Godot;
namespace GFramework.Core.Godot.extensions;
///
-/// 节点扩展方法类,提供对Godot节点的扩展功能
+/// 节点扩展方法类,提供对Godot节点的扩展功能
///
public static class NodeExtensions
{
///
- /// 安全地将节点加入删除队列,在下一帧开始时释放节点资源
+ /// 安全地将节点加入删除队列,在下一帧开始时释放节点资源
///
/// 要释放的节点实例
public static void QueueFreeX(this Node? node)
{
// 检查节点是否为空
- if (node is null)
- {
- return;
- }
+ if (node is null) return;
// 检查节点实例是否有效
- if (!GodotObject.IsInstanceValid(node))
- {
- return;
- }
+ if (!GodotObject.IsInstanceValid(node)) return;
// 检查节点是否已经加入删除队列
- if (node.IsQueuedForDeletion())
- {
- return;
- }
+ if (node.IsQueuedForDeletion()) return;
// 延迟调用QueueFree方法,避免在当前帧中直接删除节点
node.CallDeferred(Node.MethodName.QueueFree);
}
///
- /// 立即释放节点资源,不等待下一帧
+ /// 立即释放节点资源,不等待下一帧
///
/// 要立即释放的节点实例
public static void FreeX(this Node? node)
{
// 检查节点是否为空
- if (node is null)
- {
- return;
- }
+ if (node is null) return;
// 检查节点实例是否有效
- if (!GodotObject.IsInstanceValid(node))
- {
- return;
- }
+ if (!GodotObject.IsInstanceValid(node)) return;
// 检查节点是否已经加入删除队列
- if (node.IsQueuedForDeletion())
- {
- return;
- }
+ if (node.IsQueuedForDeletion()) return;
// 立即释放节点资源
node.Free();
}
///
- /// 如果节点尚未进入场景树,则等待 ready 信号。
- /// 如果已经在场景树中,则立刻返回。
+ /// 如果节点尚未进入场景树,则等待 ready 信号。
+ /// 如果已经在场景树中,则立刻返回。
///
public static async Task WaitUntilReady(this Node node)
{
- if (!node.IsInsideTree())
- {
- await node.ToSignal(node, Node.SignalName.Ready);
- }
+ if (!node.IsInsideTree()) await node.ToSignal(node, Node.SignalName.Ready);
}
///
- /// 检查节点是否有效:
- /// 1. 非 null
- /// 2. Godot 实例仍然存在(未被释放)
- /// 3. 已经加入 SceneTree
+ /// 检查节点是否有效:
+ /// 1. 非 null
+ /// 2. Godot 实例仍然存在(未被释放)
+ /// 3. 已经加入 SceneTree
///
public static bool IsValidNode(this Node? node)
{
@@ -91,12 +68,11 @@ public static class NodeExtensions
}
///
- /// 检查节点是否无效:
- /// 1. 为 null,或者
- /// 2. Godot 实例已被释放,或者
- /// 3. 尚未加入 SceneTree
- ///
- /// 返回 true 表示该节点不可用。
+ /// 检查节点是否无效:
+ /// 1. 为 null,或者
+ /// 2. Godot 实例已被释放,或者
+ /// 3. 尚未加入 SceneTree
+ /// 返回 true 表示该节点不可用。
///
public static bool IsInvalidNode(this Node? node)
{
@@ -106,7 +82,7 @@ public static class NodeExtensions
}
///
- /// 将当前节点的输入事件标记为已处理,防止事件继续向父节点传播。
+ /// 将当前节点的输入事件标记为已处理,防止事件继续向父节点传播。
///
/// 要处理输入事件的节点实例
public static void SetInputAsHandled(this Node node)
@@ -116,7 +92,7 @@ public static class NodeExtensions
}
///
- /// 设置节点所在场景树的暂停状态
+ /// 设置节点所在场景树的暂停状态
///
/// 要操作的节点对象
/// 暂停状态标识,默认为true表示暂停,false表示恢复运行
@@ -127,7 +103,7 @@ public static class NodeExtensions
}
///
- /// 查找指定名称的子节点并将其转换为指定类型
+ /// 查找指定名称的子节点并将其转换为指定类型
///
/// 要转换到的目标节点类型
/// 要在其子节点中进行查找的父节点
@@ -137,12 +113,12 @@ public static class NodeExtensions
public static T? FindChildX(this Node node, string name, bool recursive = true)
where T : Node
{
- var child = node.FindChild(name, recursive, owned: false);
+ var child = node.FindChild(name, recursive, false);
return child as T;
}
///
- /// 获取指定路径的节点,如果不存在则创建一个新的节点
+ /// 获取指定路径的节点,如果不存在则创建一个新的节点
///
/// 节点类型,必须继承自Node且具有无参构造函数
/// 父节点
@@ -163,7 +139,7 @@ public static class NodeExtensions
}
///
- /// 异步添加子节点并等待其准备就绪
+ /// 异步添加子节点并等待其准备就绪
///
/// 父节点
/// 要添加的子节点
@@ -175,7 +151,7 @@ public static class NodeExtensions
}
///
- /// 获取父节点并将其转换为指定类型
+ /// 获取父节点并将其转换为指定类型
///
/// 要转换到的目标节点类型
/// 当前节点
@@ -184,8 +160,9 @@ public static class NodeExtensions
{
return node.GetParent() as T;
}
+
///
- /// 获取场景树的根节点的第一个子节点
+ /// 获取场景树的根节点的第一个子节点
///
/// 扩展方法的目标节点
/// 根节点的第一个子节点
@@ -195,7 +172,7 @@ public static class NodeExtensions
}
///
- /// 遍历节点的所有子节点,并对指定类型的子节点执行特定操作
+ /// 遍历节点的所有子节点,并对指定类型的子节点执行特定操作
///
/// 要筛选的节点类型
/// 扩展方法的目标节点
@@ -208,7 +185,7 @@ public static class NodeExtensions
}
///
- /// 禁用节点所在场景树的输入处理功能
+ /// 禁用节点所在场景树的输入处理功能
///
/// 扩展方法的目标节点
public static void DisableInput(this Node node)
@@ -219,7 +196,7 @@ public static class NodeExtensions
}
///
- /// 启用节点所在场景树的输入处理功能
+ /// 启用节点所在场景树的输入处理功能
///
/// 扩展方法的目标节点
public static void EnableInput(this Node node)
@@ -230,7 +207,7 @@ public static class NodeExtensions
}
///
- /// 打印节点的路径信息到控制台
+ /// 打印节点的路径信息到控制台
///
/// 扩展方法的目标节点
public static void LogNodePath(this Node node)
@@ -239,7 +216,7 @@ public static class NodeExtensions
}
///
- /// 以树形结构递归打印节点及其所有子节点的名称
+ /// 以树形结构递归打印节点及其所有子节点的名称
///
/// 扩展方法的目标节点
/// 缩进字符串,用于显示层级关系
@@ -253,7 +230,7 @@ public static class NodeExtensions
}
///
- /// 安全地延迟调用指定方法,确保节点有效后再执行
+ /// 安全地延迟调用指定方法,确保节点有效后再执行
///
/// 扩展方法的目标节点
/// 要延迟调用的方法名
@@ -263,6 +240,4 @@ public static class NodeExtensions
if (node != null && GodotObject.IsInstanceValid(node))
node.CallDeferred(method);
}
-
-
}
\ No newline at end of file
diff --git a/GFramework.Core.Godot/extensions/UnRegisterExtension.cs b/GFramework.Core.Godot/extensions/UnRegisterExtension.cs
index cc6e2a8..7d3d580 100644
--- a/GFramework.Core.Godot/extensions/UnRegisterExtension.cs
+++ b/GFramework.Core.Godot/extensions/UnRegisterExtension.cs
@@ -4,12 +4,12 @@ using Godot;
namespace GFramework.Core.Godot.extensions;
///
-/// 提供取消注册扩展方法的静态类
+/// 提供取消注册扩展方法的静态类
///
public static class UnRegisterExtension
{
///
- /// 当节点退出场景树时自动取消注册监听器
+ /// 当节点退出场景树时自动取消注册监听器
///
/// 需要在节点退出时被取消注册的监听器接口实例
/// Godot节点对象,当该节点退出场景树时触发取消注册操作
diff --git a/GFramework.Core/README.md b/GFramework.Core/README.md
index c3cf1be..5d1ad2b 100644
--- a/GFramework.Core/README.md
+++ b/GFramework.Core/README.md
@@ -102,6 +102,7 @@ Event ──┘
### 为什么需要这个框架?
在传统的 Godot 开发中,我们经常遇到这些问题:
+
- 💔 **代码耦合严重**:UI 直接访问游戏逻辑,逻辑直接操作 UI
- 🔄 **难以维护**:修改一个功能需要改动多个文件
- 🐛 **难以测试**:业务逻辑和 UI 混在一起无法独立测试
@@ -133,6 +134,7 @@ public class GameArchitecture : Architecture
```
**优势**:
+
- ✅ **单例模式**:通过 `GameArchitecture.Interface` 全局访问
- ✅ **自动初始化**:注册时自动调用组件的 Init 方法
- ✅ **依赖注入**:组件自动获得架构引用,无需手动传递
@@ -173,12 +175,14 @@ public class PlayerModel : AbstractModel
```
**优势**:
+
- ✅ **数据响应式**:BindableProperty 让数据变化自动通知 UI
- ✅ **职责单一**:只存储数据,不包含复杂业务逻辑
- ✅ **易于测试**:可以独立测试数据逻辑
- ✅ **数据持久化**:可以轻松序列化整个 Model 进行存档
**为什么不在 Model 中写业务逻辑?**
+
- 保持 Model 简单纯粹,业务逻辑应该在 System 中处理
- Model 应该是"被动"的,等待其他组件修改它
@@ -209,12 +213,14 @@ public class CombatSystem : AbstractSystem
```
**优势**:
+
- ✅ **事件驱动**:通过事件解耦,不同 System 之间松耦合
- ✅ **可组合**:多个 System 协同工作,每个专注自己的领域
- ✅ **易于扩展**:新增功能只需添加新的 System 和事件监听
- ✅ **独立测试**:可以模拟事件来测试 System 的逻辑
**System 与 Model 的关系**:
+
- System 读取和修改 Model 的数据
- System 不应该存储重要的游戏状态(状态应在 Model 中)
- System 可以存储临时的计算结果或缓存
@@ -251,18 +257,21 @@ public partial class PlayerController : Node, IController
```
**优势**:
+
- ✅ **自动更新 UI**:通过 BindableProperty,数据变化自动反映到界面
- ✅ **生命周期管理**:自动注销监听,避免内存泄漏
- ✅ **分离关注点**:UI 逻辑和业务逻辑完全分离
- ✅ **易于修改 UI**:改变 UI 不影响业务逻辑
**为什么使用 RegisterWithInitValue?**
+
- 注册监听时立即获得当前值,避免 UI 显示空白
- 后续数据变化会自动触发更新
### 完成!现在你有了一个完整的架构
这 4 步完成后,你就拥有了:
+
- 📦 **清晰的数据层**(Model)
- 🧠 **独立的业务逻辑**(System)
- 🎮 **灵活的控制层**(Controller)
@@ -277,20 +286,20 @@ public partial class PlayerController : Node, IController
## 包说明
-| 包名 | 职责 | 文档 |
-|-----|------|------|
+| 包名 | 职责 | 文档 |
+|------------------|-----------------|---------------------------------|
| **architecture** | 架构核心,管理所有组件生命周期 | [📖 查看](architecture/README.md) |
-| **model** | 数据模型层,存储游戏状态 | [📖 查看](model/README.md) |
-| **system** | 业务逻辑层,处理游戏系统 | [📖 查看](system/README.md) |
-| **controller** | 控制器层,连接视图和逻辑 | [📖 查看](controller/README.md) |
-| **utility** | 工具类层,提供无状态工具 | [📖 查看](utility/README.md) |
-| **command** | 命令模式,封装写操作 | [📖 查看](command/README.md) |
-| **query** | 查询模式,封装读操作 | [📖 查看](query/README.md) |
-| **events** | 事件系统,组件间通信 | [📖 查看](events/README.md) |
-| **property** | 可绑定属性,响应式编程 | [📖 查看](property/README.md) |
-| **ioc** | IoC 容器,依赖注入 | [📖 查看](ioc/README.md) |
-| **rule** | 规则接口,定义组件约束 | [📖 查看](rule/README.md) |
-| **extensions** | 扩展方法,简化 API 调用 | [📖 查看](extensions/README.md) |
+| **model** | 数据模型层,存储游戏状态 | [📖 查看](model/README.md) |
+| **system** | 业务逻辑层,处理游戏系统 | [📖 查看](system/README.md) |
+| **controller** | 控制器层,连接视图和逻辑 | [📖 查看](controller/README.md) |
+| **utility** | 工具类层,提供无状态工具 | [📖 查看](utility/README.md) |
+| **command** | 命令模式,封装写操作 | [📖 查看](command/README.md) |
+| **query** | 查询模式,封装读操作 | [📖 查看](query/README.md) |
+| **events** | 事件系统,组件间通信 | [📖 查看](events/README.md) |
+| **property** | 可绑定属性,响应式编程 | [📖 查看](property/README.md) |
+| **ioc** | IoC 容器,依赖注入 | [📖 查看](ioc/README.md) |
+| **rule** | 规则接口,定义组件约束 | [📖 查看](rule/README.md) |
+| **extensions** | 扩展方法,简化 API 调用 | [📖 查看](extensions/README.md) |
## 组件联动
@@ -346,6 +355,7 @@ Controller: Health.RegisterWithInitValue(hp => UpdateUI(hp))
#### ✅ 好的实践 vs ❌ 坏的实践
**Model 层**:
+
```csharp
// ✅ 好:只存储数据
public class PlayerModel : AbstractModel
@@ -367,6 +377,7 @@ public class PlayerModel : AbstractModel
```
**System 层**:
+
```csharp
// ✅ 好:处理业务逻辑
public class CombatSystem : AbstractSystem
@@ -398,6 +409,7 @@ public class CombatSystem : AbstractSystem
```
**Controller 层**:
+
```csharp
// ✅ 好:只处理 UI 和用户输入
public partial class AttackButton : Button, IController
@@ -430,12 +442,12 @@ public partial class AttackButton : Button, IController
不同的通信方式适用于不同场景,选对方式能让代码更优雅。
-| 通信方式 | 使用场景 | 示例 | 优势 |
-|---------|---------|------|------|
-| **Command** | 用户操作、修改状态 | 购买物品、攻击敌人 | 可撤销、可记录 |
-| **Query** | 查询数据、检查条件 | 查询金币数量、检查是否可购买 | 明确只读意图 |
-| **Event** | 通知其他组件 | 玩家死亡、物品拾取 | 松耦合、可扩展 |
-| **BindableProperty** | 数据→UI 自动同步 | 生命值变化更新血条 | 自动化、不会遗漏 |
+| 通信方式 | 使用场景 | 示例 | 优势 |
+|----------------------|------------|----------------|----------|
+| **Command** | 用户操作、修改状态 | 购买物品、攻击敌人 | 可撤销、可记录 |
+| **Query** | 查询数据、检查条件 | 查询金币数量、检查是否可购买 | 明确只读意图 |
+| **Event** | 通知其他组件 | 玩家死亡、物品拾取 | 松耦合、可扩展 |
+| **BindableProperty** | 数据→UI 自动同步 | 生命值变化更新血条 | 自动化、不会遗漏 |
**实战示例:购物系统**
@@ -527,6 +539,7 @@ public partial class GoldDisplay : Label, IController
**为什么需要注销?**
忘记注销监听器会导致:
+
- 💥 **内存泄漏**:对象无法被 GC 回收
- 🐛 **逻辑错误**:已销毁的对象仍在响应事件
- 📉 **性能下降**:无用的监听器消耗资源
@@ -726,6 +739,7 @@ public class CombatSystemTests
```
**优势**:
+
- 不需要启动游戏就能测试逻辑
- 可以快速验证各种边界情况
- 易于进行回归测试
@@ -840,6 +854,7 @@ protected override void Init()
```
**优势总结**:
+
- 数据驱动,易于存档
- 事件解耦,易于扩展
- UI 自动化,不会遗漏更新
@@ -854,12 +869,14 @@ protected override void Init()
**理念**:每个类只负责一件事,只有一个改变的理由。
**在框架中的体现**:
+
- **Model**:只负责存储数据
- **System**:只负责处理业务逻辑
- **Controller**:只负责 UI 交互
- **Utility**:只负责提供工具方法
**好处**:
+
- 代码更容易理解和维护
- 修改一个功能不会影响其他功能
- 单元测试更简单
@@ -869,11 +886,13 @@ protected override void Init()
**理念**:对扩展开放,对修改封闭。
**在框架中的实现**:
+
- 通过**事件系统**添加新功能,无需修改现有代码
- 新的 System 可以监听现有事件,插入自己的逻辑
- 符合"插件式"的架构设计
**示例**:
+
```csharp
// 现有:战斗系统
public class CombatSystem : AbstractSystem
@@ -908,11 +927,13 @@ public class CriticalSystem : AbstractSystem
**理念**:依赖抽象(接口)而非具体实现。
**在框架中的应用**:
+
- 所有组件通过接口交互
- 通过 IoC 容器注入依赖
- 易于替换实现和编写测试
**好处**:
+
- 降低耦合度
- 易于进行单元测试(可以 mock)
- 可以灵活替换实现
@@ -922,6 +943,7 @@ public class CriticalSystem : AbstractSystem
**理念**:使用多个专门的接口,而不是一个庞大的接口。
**在框架中的体现**:
+
```csharp
// 小而专注的接口
public interface ICanGetModel : IBelongToArchitecture { }
@@ -936,6 +958,7 @@ public interface IController :
```
**优势**:
+
- 类只需要实现它真正需要的方法
- 接口更容易理解和使用
- 减少不必要的依赖
@@ -945,11 +968,13 @@ public interface IController :
**理念**:通过接口组合获得能力,而不是通过继承。
**传统继承的问题**:
+
- 继承层次深,难以理解
- 子类与父类紧密耦合
- 难以灵活组合能力
**框架的解决方案**:
+
```csharp
// ✅ 通过接口组合能力
public interface IController :
@@ -966,39 +991,44 @@ public class BattleController : GameController { }
### 框架核心设计模式 🎨
-| 设计模式 | 应用位置 | 解决的问题 | 带来的好处 |
-|---------|---------|-----------|-----------|
-| **单例模式** | Architecture | 全局唯一的架构实例 | 统一的组件管理 |
-| **工厂模式** | IoC 容器 | 组件的创建和管理 | 解耦创建逻辑 |
-| **观察者模式** | Event 系统 | 组件间的通信 | 松耦合通信 |
-| **命令模式** | Command | 封装操作请求 | 支持撤销重做 |
-| **策略模式** | System | 不同的业务逻辑 | 易于切换策略 |
-| **依赖注入** | 整体架构 | 组件间的依赖 | 自动管理依赖 |
-| **模板方法** | Abstract 类 | 定义算法骨架 | 统一流程规范 |
+| 设计模式 | 应用位置 | 解决的问题 | 带来的好处 |
+|-----------|--------------|-----------|---------|
+| **单例模式** | Architecture | 全局唯一的架构实例 | 统一的组件管理 |
+| **工厂模式** | IoC 容器 | 组件的创建和管理 | 解耦创建逻辑 |
+| **观察者模式** | Event 系统 | 组件间的通信 | 松耦合通信 |
+| **命令模式** | Command | 封装操作请求 | 支持撤销重做 |
+| **策略模式** | System | 不同的业务逻辑 | 易于切换策略 |
+| **依赖注入** | 整体架构 | 组件间的依赖 | 自动管理依赖 |
+| **模板方法** | Abstract 类 | 定义算法骨架 | 统一流程规范 |
### 为什么这样设计?🤔
#### 1. 降低学习成本
+
- 遵循业界标准模式和原则
- 有经验的开发者能快速上手
- 清晰的分层易于理解
#### 2. 提高代码质量
+
- 强制分层,避免意大利面代码
- 职责明确,减少 bug
- 易于 Code Review
#### 3. 便于团队协作
+
- 清晰的职责划分,减少冲突
- 统一的代码风格
- 新人容易融入项目
#### 4. 易于维护扩展
+
- 符合 SOLID 原则
- 通过事件添加功能无需修改现有代码
- 模块化设计,易于替换
#### 5. 支持单元测试
+
- 依赖注入让 mock 变得简单
- 接口设计便于测试
- 业务逻辑与 UI 分离,可独立测试
@@ -1006,16 +1036,19 @@ public class BattleController : GameController { }
### 架构演进建议 🚀
#### 小型项目(< 5000 行代码)
+
- 使用基础的 MVC 分层
- 适度使用 Command 和 Query
- 事件系统用于关键通知
#### 中型项目(5000-20000 行)
+
- 完整使用框架所有特性
- 细分 System 的职责
- 引入更多 Utility 复用代码
#### 大型项目(> 20000 行)
+
- 考虑按功能模块拆分多个 Architecture
- 使用事件总线连接不同模块
- 引入领域驱动设计(DDD)概念
@@ -1023,6 +1056,7 @@ public class BattleController : GameController { }
### 常见反模式 ⚠️
#### 反模式 1:上帝类(God Class)
+
```csharp
// ❌ 一个类做所有事情
public class GameManager
@@ -1042,6 +1076,7 @@ public class SaveSystem { /* 只负责存档 */ }
```
#### 反模式 2:循环依赖
+
```csharp
// ❌ A 依赖 B,B 又依赖 A
public class SystemA
@@ -1071,6 +1106,7 @@ public class SystemB
```
#### 反模式 3:过度设计
+
```csharp
// ❌ 简单功能过度抽象
public interface IClickable { }
diff --git a/GFramework.Core/architecture/Architecture.cs b/GFramework.Core/architecture/Architecture.cs
index 9ca82e4..2abab1a 100644
--- a/GFramework.Core/architecture/Architecture.cs
+++ b/GFramework.Core/architecture/Architecture.cs
@@ -9,43 +9,23 @@ using GFramework.Core.utility;
namespace GFramework.Core.architecture;
///
-/// 架构基类,提供系统、模型、工具等组件的注册与管理功能。
-/// 使用单例模式确保全局唯一实例,并支持命令、查询和事件机制。
+/// 架构基类,提供系统、模型、工具等组件的注册与管理功能。
+/// 使用单例模式确保全局唯一实例,并支持命令、查询和事件机制。
///
/// 派生类类型,用于实现单例
public abstract class Architecture : IArchitecture where T : Architecture, new()
{
///
- /// 标记架构是否已初始化完成
- ///
- private bool _mInited;
-
- ///
- /// 存储尚未初始化的系统集合,在初始化阶段统一调用Init方法
- ///
- private readonly HashSet _mSystems = [];
-
- ///
- /// 存储尚未初始化的模型集合,在初始化阶段统一调用Init方法
- ///
- private readonly HashSet _mModels = [];
-
- ///
- /// 注册补丁委托,允许在架构创建后执行额外逻辑
- ///
- public static Action OnRegisterPatch { get; set; } = _ => { };
-
- ///
- /// 静态只读字段,用于延迟初始化架构实例
- /// 使用Lazy确保线程安全的单例模式实现
+ /// 静态只读字段,用于延迟初始化架构实例
+ /// 使用Lazy确保线程安全的单例模式实现
///
///
- /// 初始化过程包括:
- /// 1. 创建T类型的实例
- /// 2. 调用用户自定义的Init方法
- /// 3. 执行注册的补丁逻辑
- /// 4. 初始化所有已注册的模型和系统
- /// 5. 清理临时集合并标记初始化完成
+ /// 初始化过程包括:
+ /// 1. 创建T类型的实例
+ /// 2. 调用用户自定义的Init方法
+ /// 3. 执行注册的补丁逻辑
+ /// 4. 初始化所有已注册的模型和系统
+ /// 5. 清理临时集合并标记初始化完成
///
/// T类型的架构实例
private static readonly Lazy MArchitectureLazy = new(() =>
@@ -58,18 +38,12 @@ public abstract class Architecture : IArchitecture where T : Architecture,
OnRegisterPatch?.Invoke(arch);
// 初始化所有已注册但尚未初始化的模型
- foreach (var model in arch._mModels)
- {
- model.Init();
- }
+ foreach (var model in arch._mModels) model.Init();
arch._mModels.Clear();
// 初始化所有已注册但尚未初始化的系统
- foreach (var system in arch._mSystems)
- {
- system.Init();
- }
+ foreach (var system in arch._mSystems) system.Init();
arch._mSystems.Clear();
@@ -78,33 +52,52 @@ public abstract class Architecture : IArchitecture where T : Architecture,
}, LazyThreadSafetyMode.ExecutionAndPublication);
///
- /// 获取架构实例的受保护静态属性
- /// 通过Lazy初始化确保只创建一个实例
+ /// 控制反转容器,用于存储和获取各种服务(如系统、模型、工具)
+ ///
+ private readonly IocContainer _mContainer = new();
+
+ ///
+ /// 存储尚未初始化的模型集合,在初始化阶段统一调用Init方法
+ ///
+ private readonly HashSet _mModels = [];
+
+ ///
+ /// 存储尚未初始化的系统集合,在初始化阶段统一调用Init方法
+ ///
+ private readonly HashSet _mSystems = [];
+
+ ///
+ /// 类型化事件系统,负责事件的发布与订阅管理
+ ///
+ private readonly TypeEventSystem _mTypeEventSystem = new();
+
+ ///
+ /// 标记架构是否已初始化完成
+ ///
+ private bool _mInited;
+
+ ///
+ /// 注册补丁委托,允许在架构创建后执行额外逻辑
+ ///
+ public static Action OnRegisterPatch { get; set; } = _ => { };
+
+ ///
+ /// 获取架构实例的受保护静态属性
+ /// 通过Lazy初始化确保只创建一个实例
///
/// T类型的架构实例
protected static T MArchitecture => MArchitectureLazy.Value;
///
- /// 获取架构实例的公共静态属性,以接口形式暴露
- /// 提供对外访问架构功能的标准接口
+ /// 获取架构实例的公共静态属性,以接口形式暴露
+ /// 提供对外访问架构功能的标准接口
///
/// IArchitecture接口类型的架构实例
public static IArchitecture Interface => MArchitectureLazy.Value;
-
///
- /// 抽象初始化方法,由子类重写以进行自定义初始化操作
- ///
- protected abstract void Init();
-
- ///
- /// 控制反转容器,用于存储和获取各种服务(如系统、模型、工具)
- ///
- private readonly IocContainer _mContainer = new();
-
- ///
- /// 注册一个系统到架构中。
- /// 若当前未初始化,则暂存至待初始化列表;否则立即初始化该系统。
+ /// 注册一个系统到架构中。
+ /// 若当前未初始化,则暂存至待初始化列表;否则立即初始化该系统。
///
/// 要注册的系统类型
/// 要注册的系统实例
@@ -114,18 +107,14 @@ public abstract class Architecture : IArchitecture where T : Architecture,
_mContainer.Register(system);
if (!_mInited)
- {
_mSystems.Add(system);
- }
else
- {
system.Init();
- }
}
///
- /// 注册一个模型到架构中。
- /// 若当前未初始化,则暂存至待初始化列表;否则立即初始化该模型。
+ /// 注册一个模型到架构中。
+ /// 若当前未初始化,则暂存至待初始化列表;否则立即初始化该模型。
///
/// 要注册的模型类型
/// 要注册的模型实例
@@ -135,62 +124,132 @@ public abstract class Architecture : IArchitecture where T : Architecture,
_mContainer.Register(model);
if (!_mInited)
- {
_mModels.Add(model);
- }
else
- {
model.Init();
- }
}
///
- /// 注册一个工具到架构中。
- /// 工具不会被延迟初始化,直接放入IOC容器供后续使用。
+ /// 注册一个工具到架构中。
+ /// 工具不会被延迟初始化,直接放入IOC容器供后续使用。
///
/// 要注册的工具类型
/// 要注册的工具实例
- public void RegisterUtility(TUtility utility) where TUtility : IUtility =>
+ public void RegisterUtility(TUtility utility) where TUtility : IUtility
+ {
_mContainer.Register(utility);
+ }
///
- /// 从IOC容器中获取指定类型的系统实例
+ /// 从IOC容器中获取指定类型的系统实例
///
/// 目标系统类型
/// 对应的系统实例
- public TSystem GetSystem() where TSystem : class, ISystem => _mContainer.Get();
+ public TSystem GetSystem() where TSystem : class, ISystem
+ {
+ return _mContainer.Get();
+ }
///
- /// 从IOC容器中获取指定类型的模型实例
+ /// 从IOC容器中获取指定类型的模型实例
///
/// 目标模型类型
/// 对应的模型实例
- public TModel GetModel() where TModel : class, IModel => _mContainer.Get();
+ public TModel GetModel() where TModel : class, IModel
+ {
+ return _mContainer.Get();
+ }
///
- /// 从IOC容器中获取指定类型的工具实例
+ /// 从IOC容器中获取指定类型的工具实例
///
/// 目标工具类型
/// 对应的工具实例
- public TUtility GetUtility() where TUtility : class, IUtility => _mContainer.Get();
+ public TUtility GetUtility() where TUtility : class, IUtility
+ {
+ return _mContainer.Get();
+ }
///
- /// 发送一个带返回结果的命令请求
+ /// 发送一个带返回结果的命令请求
///
/// 命令执行后的返回值类型
/// 要发送的命令对象
/// 命令执行的结果
- public TResult SendCommand(ICommand command) => ExecuteCommand(command);
+ public TResult SendCommand(ICommand command)
+ {
+ return ExecuteCommand(command);
+ }
///
- /// 发送一个无返回结果的命令请求
+ /// 发送一个无返回结果的命令请求
///
/// 命令的具体类型
/// 要发送的命令对象
- public void SendCommand(TCommand command) where TCommand : ICommand => ExecuteCommand(command);
+ public void SendCommand(TCommand command) where TCommand : ICommand
+ {
+ ExecuteCommand(command);
+ }
///
- /// 执行一个带返回结果的命令
+ /// 发起一次查询请求并获得其结果
+ ///
+ /// 查询结果的数据类型
+ /// 要发起的查询对象
+ /// 查询得到的结果数据
+ public TResult SendQuery(IQuery query)
+ {
+ return DoQuery(query);
+ }
+
+ ///
+ /// 发布一个默认构造的新事件对象
+ ///
+ /// 事件类型
+ public void SendEvent() where TEvent : new()
+ {
+ _mTypeEventSystem.Send();
+ }
+
+ ///
+ /// 发布一个具体的事件对象
+ ///
+ /// 事件类型
+ /// 要发布的事件实例
+ public void SendEvent(TEvent e)
+ {
+ _mTypeEventSystem.Send(e);
+ }
+
+ ///
+ /// 订阅某个特定类型的事件
+ ///
+ /// 事件类型
+ /// 当事件发生时触发的动作
+ /// 可用于取消订阅的对象
+ public IUnRegister RegisterEvent(Action onEvent)
+ {
+ return _mTypeEventSystem.Register(onEvent);
+ }
+
+ ///
+ /// 取消对某类型事件的监听
+ ///
+ /// 事件类型
+ /// 之前绑定的事件处理器
+ public void UnRegisterEvent(Action onEvent)
+ {
+ _mTypeEventSystem.UnRegister(onEvent);
+ }
+
+
+ ///
+ /// 抽象初始化方法,由子类重写以进行自定义初始化操作
+ ///
+ protected abstract void Init();
+
+ ///
+ /// 执行一个带返回结果的命令
///
/// 命令执行后的返回值类型
/// 要执行的命令对象
@@ -202,7 +261,7 @@ public abstract class Architecture : IArchitecture where T : Architecture,
}
///
- /// 执行一个无返回结果的命令
+ /// 执行一个无返回结果的命令
///
/// 要执行的命令对象
protected virtual void ExecuteCommand(ICommand command)
@@ -212,15 +271,7 @@ public abstract class Architecture : IArchitecture where T : Architecture,
}
///
- /// 发起一次查询请求并获得其结果
- ///
- /// 查询结果的数据类型
- /// 要发起的查询对象
- /// 查询得到的结果数据
- public TResult SendQuery(IQuery query) => DoQuery(query);
-
- ///
- /// 实际执行查询逻辑的方法
+ /// 实际执行查询逻辑的方法
///
/// 查询结果的数据类型
/// 要处理的查询对象
@@ -230,37 +281,4 @@ public abstract class Architecture : IArchitecture where T : Architecture,
query.SetArchitecture(this);
return query.Do();
}
-
- ///
- /// 类型化事件系统,负责事件的发布与订阅管理
- ///
- private readonly TypeEventSystem _mTypeEventSystem = new();
-
- ///
- /// 发布一个默认构造的新事件对象
- ///
- /// 事件类型
- public void SendEvent() where TEvent : new() => _mTypeEventSystem.Send();
-
- ///
- /// 发布一个具体的事件对象
- ///
- /// 事件类型
- /// 要发布的事件实例
- public void SendEvent(TEvent e) => _mTypeEventSystem.Send(e);
-
- ///
- /// 订阅某个特定类型的事件
- ///
- /// 事件类型
- /// 当事件发生时触发的动作
- /// 可用于取消订阅的对象
- public IUnRegister RegisterEvent(Action onEvent) => _mTypeEventSystem.Register(onEvent);
-
- ///
- /// 取消对某类型事件的监听
- ///
- /// 事件类型
- /// 之前绑定的事件处理器
- public void UnRegisterEvent(Action onEvent) => _mTypeEventSystem.UnRegister(onEvent);
}
\ No newline at end of file
diff --git a/GFramework.Core/architecture/IArchitecture.cs b/GFramework.Core/architecture/IArchitecture.cs
index 642d677..dd5c54d 100644
--- a/GFramework.Core/architecture/IArchitecture.cs
+++ b/GFramework.Core/architecture/IArchitecture.cs
@@ -8,62 +8,62 @@ using GFramework.Core.utility;
namespace GFramework.Core.architecture;
///
-/// 架构接口,定义了应用程序架构的核心功能,包括系统、模型、工具的注册和获取,
-/// 以及命令、查询、事件的发送和处理机制
+/// 架构接口,定义了应用程序架构的核心功能,包括系统、模型、工具的注册和获取,
+/// 以及命令、查询、事件的发送和处理机制
///
public interface IArchitecture
{
///
- /// 注册系统实例到架构中
+ /// 注册系统实例到架构中
///
/// 系统类型,必须实现ISystem接口
/// 要注册的系统实例
void RegisterSystem(T system) where T : ISystem;
///
- /// 注册模型实例到架构中
+ /// 注册模型实例到架构中
///
/// 模型类型,必须实现IModel接口
/// 要注册的模型实例
void RegisterModel(T model) where T : IModel;
///
- /// 注册工具实例到架构中
+ /// 注册工具实例到架构中
///
/// 工具类型,必须实现IUtility接口
/// 要注册的工具实例
void RegisterUtility(T utility) where T : IUtility;
///
- /// 从架构中获取指定类型的系统实例
+ /// 从架构中获取指定类型的系统实例
///
/// 系统类型,必须是class且实现ISystem接口
/// 指定类型的系统实例
T GetSystem() where T : class, ISystem;
///
- /// 从架构中获取指定类型的模型实例
+ /// 从架构中获取指定类型的模型实例
///
/// 模型类型,必须是class且实现IModel接口
/// 指定类型的模型实例
T GetModel() where T : class, IModel;
///
- /// 从架构中获取指定类型的工具实例
+ /// 从架构中获取指定类型的工具实例
///
/// 工具类型,必须是class且实现IUtility接口
/// 指定类型的工具实例
T GetUtility() where T : class, IUtility;
///
- /// 发送并执行指定的命令
+ /// 发送并执行指定的命令
///
/// 命令类型,必须实现ICommand接口
/// 要执行的命令实例
void SendCommand(T command) where T : ICommand;
///
- /// 发送并执行带有返回值的命令
+ /// 发送并执行带有返回值的命令
///
/// 命令执行结果的类型
/// 要执行的命令实例
@@ -71,7 +71,7 @@ public interface IArchitecture
TResult SendCommand(ICommand command);
///
- /// 发送并执行查询操作
+ /// 发送并执行查询操作
///
/// 查询结果的类型
/// 要执行的查询实例
@@ -79,20 +79,20 @@ public interface IArchitecture
TResult SendQuery(IQuery query);
///
- /// 发送无参事件
+ /// 发送无参事件
///
/// 事件类型,必须具有无参构造函数
void SendEvent() where T : new();
///
- /// 发送指定的事件实例
+ /// 发送指定的事件实例
///
/// 事件类型
/// 要发送的事件实例
void SendEvent(T e);
///
- /// 注册事件监听器
+ /// 注册事件监听器
///
/// 事件类型
/// 事件触发时的回调方法
@@ -100,9 +100,9 @@ public interface IArchitecture
IUnRegister RegisterEvent(Action onEvent);
///
- /// 取消注册事件监听器
+ /// 取消注册事件监听器
///
/// 事件类型
/// 要取消注册的事件回调方法
void UnRegisterEvent(Action onEvent);
-}
+}
\ No newline at end of file
diff --git a/GFramework.Core/architecture/README.md b/GFramework.Core/architecture/README.md
index 939aa8f..96a75b4 100644
--- a/GFramework.Core/architecture/README.md
+++ b/GFramework.Core/architecture/README.md
@@ -11,6 +11,7 @@ Architecture 包是整个框架的核心,提供了基于 MVC 架构模式的
架构接口,定义了框架的核心功能契约。
**主要职责:**
+
- 组件注册:注册 System、Model、Utility
- 组件获取:从容器中获取已注册的组件
- 命令处理:发送并执行命令
@@ -49,6 +50,7 @@ void UnRegisterEvent(Action onEvent);
架构基类,实现了 [`IArchitecture`](IArchitecture.cs) 接口,提供完整的架构功能实现。
**特性:**
+
- **单例模式**:使用泛型和 `Lazy` 确保全局唯一实例
- **线程安全**:采用 `LazyThreadSafetyMode.ExecutionAndPublication` 保证多线程安全
- **生命周期管理**:自动管理 System 和 Model 的初始化顺序
@@ -56,6 +58,7 @@ void UnRegisterEvent(Action onEvent);
- **事件系统**:集成类型化事件系统,支持类型安全的事件通信
**初始化流程:**
+
1. 创建架构实例
2. 调用用户自定义的 `Init()` 方法
3. 执行注册的补丁逻辑(`OnRegisterPatch`)
@@ -133,27 +136,32 @@ GameArchitecture.Interface.RegisterSystem(newSystem);
## 设计模式
### 单例模式
+
通过泛型约束和 `Lazy` 实现类型安全的单例。
### 依赖注入(IoC)
+
使用内置 IoC 容器管理组件生命周期和依赖关系。
### 命令模式
+
通过 [`ICommand`](../command/ICommand.cs) 封装所有用户操作。
### 查询模式(CQRS)
+
通过 [`IQuery`](../query/IQuery.cs) 分离查询和命令操作。
### 观察者模式
+
通过事件系统实现组件间的松耦合通信。
## 最佳实践
1. **保持架构类简洁**:只在 `Init()` 中注册组件,不要包含业务逻辑
2. **合理划分职责**:
- - Model:数据和状态
- - System:业务逻辑和规则
- - Utility:无状态的工具方法
+ - Model:数据和状态
+ - System:业务逻辑和规则
+ - Utility:无状态的工具方法
3. **使用接口访问**:通过 `Interface` 属性访问架构,便于测试
4. **事件命名规范**:使用过去式命名事件类,如 `PlayerDiedEvent`
5. **避免循环依赖**:System 不应直接引用 System,应通过事件通信
diff --git a/GFramework.Core/command/AbstractCommand.cs b/GFramework.Core/command/AbstractCommand.cs
index 36c86fa..9618bab 100644
--- a/GFramework.Core/command/AbstractCommand.cs
+++ b/GFramework.Core/command/AbstractCommand.cs
@@ -4,37 +4,46 @@ using GFramework.Core.rule;
namespace GFramework.Core.command;
///
-/// 抽象命令类,实现 ICommand 接口,为具体命令提供基础架构支持
+/// 抽象命令类,实现 ICommand 接口,为具体命令提供基础架构支持
///
public abstract class AbstractCommand : ICommand
{
private IArchitecture _mArchitecture;
///
- /// 获取命令所属的架构实例
+ /// 获取命令所属的架构实例
///
/// IArchitecture 架构接口实例
- IArchitecture IBelongToArchitecture.GetArchitecture() => _mArchitecture;
+ IArchitecture IBelongToArchitecture.GetArchitecture()
+ {
+ return _mArchitecture;
+ }
///
- /// 设置命令所属的架构实例
+ /// 设置命令所属的架构实例
///
/// 要设置的架构实例
- void ICanSetArchitecture.SetArchitecture(IArchitecture architecture) => _mArchitecture = architecture;
+ void ICanSetArchitecture.SetArchitecture(IArchitecture architecture)
+ {
+ _mArchitecture = architecture;
+ }
///
- /// 执行命令,调用抽象方法 OnExecute 来实现具体逻辑
+ /// 执行命令,调用抽象方法 OnExecute 来实现具体逻辑
///
- void ICommand.Execute() => OnExecute();
+ void ICommand.Execute()
+ {
+ OnExecute();
+ }
///
- /// 抽象方法,由子类实现具体的命令执行逻辑
+ /// 抽象方法,由子类实现具体的命令执行逻辑
///
protected abstract void OnExecute();
}
///
-/// 带返回值的抽象命令类,实现 ICommand{TResult} 接口,为需要返回结果的命令提供基础架构支持
+/// 带返回值的抽象命令类,实现 ICommand{TResult} 接口,为需要返回结果的命令提供基础架构支持
///
/// 命令执行后返回的结果类型
public abstract class AbstractCommand : ICommand
@@ -42,26 +51,35 @@ public abstract class AbstractCommand : ICommand
private IArchitecture _mArchitecture;
///
- /// 获取命令所属的架构实例
+ /// 获取命令所属的架构实例
///
/// IArchitecture 架构接口实例
- IArchitecture IBelongToArchitecture.GetArchitecture() => _mArchitecture;
+ IArchitecture IBelongToArchitecture.GetArchitecture()
+ {
+ return _mArchitecture;
+ }
///
- /// 设置命令所属的架构实例
+ /// 设置命令所属的架构实例
///
/// 要设置的架构实例
- void ICanSetArchitecture.SetArchitecture(IArchitecture architecture) => _mArchitecture = architecture;
+ void ICanSetArchitecture.SetArchitecture(IArchitecture architecture)
+ {
+ _mArchitecture = architecture;
+ }
///
- /// 执行命令,调用抽象方法 OnExecute 来实现具体逻辑并返回结果
+ /// 执行命令,调用抽象方法 OnExecute 来实现具体逻辑并返回结果
///
/// TResult 类型的执行结果
- TResult ICommand.Execute() => OnExecute();
+ TResult ICommand.Execute()
+ {
+ return OnExecute();
+ }
///
- /// 抽象方法,由子类实现具体的命令执行逻辑
+ /// 抽象方法,由子类实现具体的命令执行逻辑
///
/// TResult 类型的执行结果
protected abstract TResult OnExecute();
-}
+}
\ No newline at end of file
diff --git a/GFramework.Core/command/ICanSendCommand.cs b/GFramework.Core/command/ICanSendCommand.cs
index f863581..47d3d08 100644
--- a/GFramework.Core/command/ICanSendCommand.cs
+++ b/GFramework.Core/command/ICanSendCommand.cs
@@ -3,7 +3,7 @@ using GFramework.Core.rule;
namespace GFramework.Core.command;
///
-/// 定义一个可以发送命令的接口,继承自IBelongToArchitecture接口。
-/// 该接口用于标识那些具备发送命令能力的架构组件。
+/// 定义一个可以发送命令的接口,继承自IBelongToArchitecture接口。
+/// 该接口用于标识那些具备发送命令能力的架构组件。
///
-public interface ICanSendCommand : IBelongToArchitecture;
+public interface ICanSendCommand : IBelongToArchitecture;
\ No newline at end of file
diff --git a/GFramework.Core/command/ICommand.cs b/GFramework.Core/command/ICommand.cs
index b0ec155..047e749 100644
--- a/GFramework.Core/command/ICommand.cs
+++ b/GFramework.Core/command/ICommand.cs
@@ -8,22 +8,22 @@ using GFramework.Core.utility;
namespace GFramework.Core.command;
///
-/// 命令接口,定义了无返回值命令的基本契约
-/// 该接口继承了多个框架能力接口,使命令可以访问架构、系统、模型、工具,并能够发送事件、命令和查询
+/// 命令接口,定义了无返回值命令的基本契约
+/// 该接口继承了多个框架能力接口,使命令可以访问架构、系统、模型、工具,并能够发送事件、命令和查询
///
public interface ICommand : ICanSetArchitecture, ICanGetSystem, ICanGetModel, ICanGetUtility,
ICanSendEvent, ICanSendCommand, ICanSendQuery
{
///
- /// 执行命令的核心方法
- /// 该方法不接受参数且无返回值,具体实现由派生类完成
+ /// 执行命令的核心方法
+ /// 该方法不接受参数且无返回值,具体实现由派生类完成
///
void Execute();
}
///
-/// 带返回值的命令接口,定义了有返回值命令的基本契约
-/// 该接口继承了多个框架能力接口,使命令可以访问架构、系统、模型、工具,并能够发送事件、命令和查询
+/// 带返回值的命令接口,定义了有返回值命令的基本契约
+/// 该接口继承了多个框架能力接口,使命令可以访问架构、系统、模型、工具,并能够发送事件、命令和查询
///
/// 命令执行后返回的结果类型
public interface ICommand : ICanSetArchitecture, ICanGetSystem, ICanGetModel,
@@ -31,9 +31,9 @@ public interface ICommand : ICanSetArchitecture, ICanGetSystem, ICa
ICanSendEvent, ICanSendCommand, ICanSendQuery
{
///
- /// 执行命令的核心方法
- /// 该方法不接受参数,但会返回指定类型的结果
+ /// 执行命令的核心方法
+ /// 该方法不接受参数,但会返回指定类型的结果
///
/// 命令执行后的结果,类型为 TResult
TResult Execute();
-}
+}
\ No newline at end of file
diff --git a/GFramework.Core/command/README.md b/GFramework.Core/command/README.md
index 931763b..f91e041 100644
--- a/GFramework.Core/command/README.md
+++ b/GFramework.Core/command/README.md
@@ -11,6 +11,7 @@ Command 包实现了命令模式(Command Pattern),用于封装用户操作
无返回值命令接口,定义了命令的基本契约。
**继承的能力接口:**
+
- [`ICanSetArchitecture`](../rule/ICanSetArchitecture.cs) - 可设置架构
- [`ICanGetSystem`](../system/ICanGetSystem.cs) - 可获取系统
- [`ICanGetModel`](../model/ICanGetModel.cs) - 可获取模型
@@ -20,6 +21,7 @@ Command 包实现了命令模式(Command Pattern),用于封装用户操作
- [`ICanSendQuery`](../query/ICanSendQuery.cs) - 可发送查询
**核心方法:**
+
```csharp
void Execute(); // 执行命令
```
@@ -29,6 +31,7 @@ void Execute(); // 执行命令
带返回值的命令接口,用于需要返回执行结果的命令。
**核心方法:**
+
```csharp
TResult Execute(); // 执行命令并返回结果
```
@@ -232,12 +235,14 @@ public class LoginCommand : AbstractCommand
## 命令 vs 系统方法
**何时使用命令:**
+
- 需要参数化操作
- 需要记录操作历史(用于撤销/重做)
- 操作需要跨多个系统协调
- 用户触发的离散操作
**何时使用系统方法:**
+
- 持续运行的逻辑(如每帧更新)
- 系统内部的私有逻辑
- 不需要外部调用的功能
diff --git a/GFramework.Core/controller/IController.cs b/GFramework.Core/controller/IController.cs
index 3b5e9c6..1bc4733 100644
--- a/GFramework.Core/controller/IController.cs
+++ b/GFramework.Core/controller/IController.cs
@@ -8,9 +8,9 @@ using GFramework.Core.utility;
namespace GFramework.Core.controller;
///
-/// 控制器接口,定义了控制器需要实现的所有功能契约
-/// 该接口继承了多个框架核心接口,用于支持控制器的各种能力
-/// 包括架构归属、命令发送、系统获取、模型获取、事件注册、查询发送和工具获取等功能
+/// 控制器接口,定义了控制器需要实现的所有功能契约
+/// 该接口继承了多个框架核心接口,用于支持控制器的各种能力
+/// 包括架构归属、命令发送、系统获取、模型获取、事件注册、查询发送和工具获取等功能
///
public interface IController : ICanSendCommand, ICanGetSystem, ICanGetModel,
- ICanRegisterEvent, ICanSendQuery, ICanGetUtility;
+ ICanRegisterEvent, ICanSendQuery, ICanGetUtility;
\ No newline at end of file
diff --git a/GFramework.Core/controller/README.md b/GFramework.Core/controller/README.md
index 15d2f59..98378f5 100644
--- a/GFramework.Core/controller/README.md
+++ b/GFramework.Core/controller/README.md
@@ -2,7 +2,8 @@
## 概述
-Controller 包定义了控制器(Controller)的接口规范。控制器是 MVC 架构中的 C 层,负责处理用户交互、协调视图和模型,是连接表现层和业务层的桥梁。在本框架中,Controller 通常对应 Godot 的节点脚本。
+Controller 包定义了控制器(Controller)的接口规范。控制器是 MVC 架构中的 C
+层,负责处理用户交互、协调视图和模型,是连接表现层和业务层的桥梁。在本框架中,Controller 通常对应 Godot 的节点脚本。
## 核心接口
@@ -11,6 +12,7 @@ Controller 包定义了控制器(Controller)的接口规范。控制器是 M
控制器接口,定义了控制器需要实现的所有功能契约。
**继承的能力接口:**
+
- [`ICanSendCommand`](../command/ICanSendCommand.cs) - 可发送命令
- [`ICanGetSystem`](../system/ICanGetSystem.cs) - 可获取系统
- [`ICanGetModel`](../model/ICanGetModel.cs) - 可获取模型
@@ -21,6 +23,7 @@ Controller 包定义了控制器(Controller)的接口规范。控制器是 M
**能力说明:**
控制器拥有框架中最全面的能力集合,可以:
+
1. 发送命令执行业务逻辑
2. 获取系统调用服务
3. 获取模型读写数据
@@ -224,40 +227,40 @@ public partial class CombatController : Node, IController
### ✅ 应该做的事
1. **处理用户输入**
- - 键盘、鼠标、触摸输入
- - UI 按钮点击
- - 手势识别
+ - 键盘、鼠标、触摸输入
+ - UI 按钮点击
+ - 手势识别
2. **协调视图和模型**
- - 监听模型变化更新视图
- - 将用户操作转换为命令
+ - 监听模型变化更新视图
+ - 将用户操作转换为命令
3. **管理界面逻辑**
- - UI 元素的显示/隐藏
- - 动画播放控制
- - 视觉反馈
+ - UI 元素的显示/隐藏
+ - 动画播放控制
+ - 视觉反馈
4. **事件监听**
- - 注册关心的事件
- - 响应事件更新界面
+ - 注册关心的事件
+ - 响应事件更新界面
### ❌ 不应该做的事
1. **不包含业务逻辑**
- - 业务逻辑应该在 System 中
- - 控制器只负责调用和协调
+ - 业务逻辑应该在 System 中
+ - 控制器只负责调用和协调
2. **不直接修改模型**
- - 应该通过 Command 修改模型
- - 避免直接访问 Model 的 setter
+ - 应该通过 Command 修改模型
+ - 避免直接访问 Model 的 setter
3. **不处理复杂计算**
- - 复杂计算应该在 Query 或 System 中
- - 控制器保持简洁
+ - 复杂计算应该在 Query 或 System 中
+ - 控制器保持简洁
4. **不保存核心状态**
- - 核心状态应该在 Model 中
- - 控制器可以保存临时 UI 状态
+ - 核心状态应该在 Model 中
+ - 控制器可以保存临时 UI 状态
## 生命周期管理
@@ -326,28 +329,28 @@ public partial class GameController : Node, IController
## 最佳实践
1. **一个控制器对应一个视图**
- - 每个 Godot 场景/节点有对应的控制器
- - 避免一个控制器管理多个不相关的视图
+ - 每个 Godot 场景/节点有对应的控制器
+ - 避免一个控制器管理多个不相关的视图
2. **使用依赖注入获取依赖**
- - 通过 `GetModel()`、`GetSystem()` 获取依赖
- - 不要在构造函数中获取,应在 `_Ready()` 中
+ - 通过 `GetModel()`、`GetSystem()` 获取依赖
+ - 不要在构造函数中获取,应在 `_Ready()` 中
3. **保持控制器轻量**
- - 复杂逻辑放在 Command、Query、System 中
- - 控制器只做协调和转发
+ - 复杂逻辑放在 Command、Query、System 中
+ - 控制器只做协调和转发
4. **合理使用缓存**
- - 频繁使用的 Model、System 可以缓存引用
- - 平衡性能和内存占用
+ - 频繁使用的 Model、System 可以缓存引用
+ - 平衡性能和内存占用
5. **统一管理事件注销**
- - 使用 `IUnRegisterList` 统一管理
- - 在 `_ExitTree()` 中统一注销
+ - 使用 `IUnRegisterList` 统一管理
+ - 在 `_ExitTree()` 中统一注销
6. **命名规范**
- - 控制器类名:`XxxController`
- - 继承 Godot 节点:`Node`、`Control`、`Node2D` 等
+ - 控制器类名:`XxxController`
+ - 继承 Godot 节点:`Node`、`Control`、`Node2D` 等
## 常见模式
diff --git a/GFramework.Core/events/DefaultUnRegister.cs b/GFramework.Core/events/DefaultUnRegister.cs
index e71da4a..78cb95c 100644
--- a/GFramework.Core/events/DefaultUnRegister.cs
+++ b/GFramework.Core/events/DefaultUnRegister.cs
@@ -1,16 +1,15 @@
namespace GFramework.Core.events;
-
///
-/// 默认注销器类,用于执行注销操作
+/// 默认注销器类,用于执行注销操作
///
/// 注销时要执行的回调函数
-public class DefaultUnRegister(Action onUnRegister): IUnRegister
+public class DefaultUnRegister(Action onUnRegister) : IUnRegister
{
private Action _mOnUnRegister = onUnRegister;
///
- /// 执行注销操作,调用注册的回调函数并清理引用
+ /// 执行注销操作,调用注册的回调函数并清理引用
///
public void UnRegister()
{
@@ -18,4 +17,4 @@ public class DefaultUnRegister(Action onUnRegister): IUnRegister
_mOnUnRegister.Invoke();
_mOnUnRegister = null;
}
-}
+}
\ No newline at end of file
diff --git a/GFramework.Core/events/EasyEvent.cs b/GFramework.Core/events/EasyEvent.cs
index f2a446f..cfc9aca 100644
--- a/GFramework.Core/events/EasyEvent.cs
+++ b/GFramework.Core/events/EasyEvent.cs
@@ -1,14 +1,14 @@
namespace GFramework.Core.events;
///
-/// 简单事件类,用于注册、注销和触发无参事件回调
+/// 简单事件类,用于注册、注销和触发无参事件回调
///
public class EasyEvent
{
private Action _mOnEvent = () => { };
///
- /// 注册事件回调函数
+ /// 注册事件回调函数
///
/// 要注册的事件回调函数
/// 用于注销事件的 unregister 对象
@@ -19,13 +19,19 @@ public class EasyEvent
}
///
- /// 注销已注册的事件回调函数
+ /// 注销已注册的事件回调函数
///
/// 要注销的事件回调函数
- public void UnRegister(Action onEvent) => _mOnEvent -= onEvent;
+ public void UnRegister(Action onEvent)
+ {
+ _mOnEvent -= onEvent;
+ }
///
- /// 触发所有已注册的事件回调函数
+ /// 触发所有已注册的事件回调函数
///
- public void Trigger() => _mOnEvent?.Invoke();
-}
+ public void Trigger()
+ {
+ _mOnEvent?.Invoke();
+ }
+}
\ No newline at end of file
diff --git a/GFramework.Core/events/EasyEventGeneric.cs b/GFramework.Core/events/EasyEventGeneric.cs
index 4f7d17c..129d0f5 100644
--- a/GFramework.Core/events/EasyEventGeneric.cs
+++ b/GFramework.Core/events/EasyEventGeneric.cs
@@ -1,20 +1,36 @@
namespace GFramework.Core.events;
///
-/// 泛型事件类,支持一个泛型参数 T 的事件注册、注销与触发。
-/// 实现了 IEasyEvent 接口以提供统一的事件操作接口。
+/// 泛型事件类,支持一个泛型参数 T 的事件注册、注销与触发。
+/// 实现了 IEasyEvent 接口以提供统一的事件操作接口。
///
/// 事件回调函数的第一个参数类型。
public class EasyEvent : IEasyEvent
{
///
- /// 存储已注册的事件处理委托。
- /// 默认为空操作(no-op)委托,避免 null 检查。
+ /// 存储已注册的事件处理委托。
+ /// 默认为空操作(no-op)委托,避免 null 检查。
///
private Action _mOnEvent = e => { };
///
- /// 注册一个事件监听器,并返回可用于取消注册的对象。
+ /// 显式实现 IEasyEvent 接口中的 Register 方法。
+ /// 允许使用无参 Action 来订阅当前带参事件。
+ ///
+ /// 无参事件处理方法。
+ /// IUnRegister 对象,用于稍后注销该事件监听器。
+ IUnRegister IEasyEvent.Register(Action onEvent)
+ {
+ return Register(Action);
+
+ void Action(T _)
+ {
+ onEvent();
+ }
+ }
+
+ ///
+ /// 注册一个事件监听器,并返回可用于取消注册的对象。
///
/// 要注册的事件处理方法。
/// IUnRegister 对象,用于稍后注销该事件监听器。
@@ -25,46 +41,56 @@ public class EasyEvent : IEasyEvent
}
///
- /// 取消指定的事件监听器。
+ /// 取消指定的事件监听器。
///
/// 需要被注销的事件处理方法。
- public void UnRegister(Action onEvent) => _mOnEvent -= onEvent;
+ public void UnRegister(Action onEvent)
+ {
+ _mOnEvent -= onEvent;
+ }
///
- /// 触发所有已注册的事件处理程序,并传递参数 t。
+ /// 触发所有已注册的事件处理程序,并传递参数 t。
///
/// 传递给事件处理程序的参数。
- public void Trigger(T t) => _mOnEvent?.Invoke(t);
-
- ///
- /// 显式实现 IEasyEvent 接口中的 Register 方法。
- /// 允许使用无参 Action 来订阅当前带参事件。
- ///
- /// 无参事件处理方法。
- /// IUnRegister 对象,用于稍后注销该事件监听器。
- IUnRegister IEasyEvent.Register(Action onEvent)
+ public void Trigger(T t)
{
- return Register(Action);
- void Action(T _) => onEvent();
+ _mOnEvent?.Invoke(t);
}
}
///
-/// 支持两个泛型参数 T 和 TK 的事件类。
-/// 提供事件注册、注销和触发功能。
+/// 支持两个泛型参数 T 和 TK 的事件类。
+/// 提供事件注册、注销和触发功能。
///
/// 第一个参数类型。
/// 第二个参数类型。
public class EasyEvent : IEasyEvent
{
///
- /// 存储已注册的双参数事件处理委托。
- /// 默认为空操作(no-op)委托。
+ /// 存储已注册的双参数事件处理委托。
+ /// 默认为空操作(no-op)委托。
///
private Action _mOnEvent = (_, _) => { };
///
- /// 注册一个接受两个参数的事件监听器,并返回可用于取消注册的对象。
+ /// 显式实现 IEasyEvent 接口中的 Register 方法。
+ /// 允许使用无参 Action 来订阅当前带参事件。
+ ///
+ /// 无参事件处理方法。
+ /// IUnRegister 对象,用于稍后注销该事件监听器。
+ IUnRegister IEasyEvent.Register(Action onEvent)
+ {
+ return Register(Action);
+
+ void Action(T _, TK __)
+ {
+ onEvent();
+ }
+ }
+
+ ///
+ /// 注册一个接受两个参数的事件监听器,并返回可用于取消注册的对象。
///
/// 要注册的事件处理方法。
/// IUnRegister 对象,用于稍后注销该事件监听器。
@@ -75,34 +101,28 @@ public class EasyEvent : IEasyEvent
}
///
- /// 取消指定的双参数事件监听器。
+ /// 取消指定的双参数事件监听器。
///
/// 需要被注销的事件处理方法。
- public void UnRegister(Action onEvent) => _mOnEvent -= onEvent;
+ public void UnRegister(Action onEvent)
+ {
+ _mOnEvent -= onEvent;
+ }
///
- /// 触发所有已注册的事件处理程序,并传递参数 t 和 k。
+ /// 触发所有已注册的事件处理程序,并传递参数 t 和 k。
///
/// 第一个参数。
/// 第二个参数。
- public void Trigger(T t, TK k) => _mOnEvent?.Invoke(t, k);
-
- ///
- /// 显式实现 IEasyEvent 接口中的 Register 方法。
- /// 允许使用无参 Action 来订阅当前带参事件。
- ///
- /// 无参事件处理方法。
- /// IUnRegister 对象,用于稍后注销该事件监听器。
- IUnRegister IEasyEvent.Register(Action onEvent)
+ public void Trigger(T t, TK k)
{
- return Register(Action);
- void Action(T _, TK __) => onEvent();
+ _mOnEvent?.Invoke(t, k);
}
}
///
-/// 支持三个泛型参数 T、TK 和 TS 的事件类。
-/// 提供事件注册、注销和触发功能。
+/// 支持三个泛型参数 T、TK 和 TS 的事件类。
+/// 提供事件注册、注销和触发功能。
///
/// 第一个参数类型。
/// 第二个参数类型。
@@ -110,13 +130,29 @@ public class EasyEvent : IEasyEvent
public class EasyEvent : IEasyEvent
{
///
- /// 存储已注册的三参数事件处理委托。
- /// 默认为空操作(no-op)委托。
+ /// 存储已注册的三参数事件处理委托。
+ /// 默认为空操作(no-op)委托。
///
private Action _mOnEvent = (_, _, _) => { };
///
- /// 注册一个接受三个参数的事件监听器,并返回可用于取消注册的对象。
+ /// 显式实现 IEasyEvent 接口中的 Register 方法。
+ /// 允许使用无参 Action 来订阅当前带参事件。
+ ///
+ /// 无参事件处理方法。
+ /// IUnRegister 对象,用于稍后注销该事件监听器。
+ IUnRegister IEasyEvent.Register(Action onEvent)
+ {
+ return Register(Action);
+
+ void Action(T _, TK __, TS ___)
+ {
+ onEvent();
+ }
+ }
+
+ ///
+ /// 注册一个接受三个参数的事件监听器,并返回可用于取消注册的对象。
///
/// 要注册的事件处理方法。
/// IUnRegister 对象,用于稍后注销该事件监听器。
@@ -127,28 +163,22 @@ public class EasyEvent : IEasyEvent
}
///
- /// 取消指定的三参数事件监听器。
+ /// 取消指定的三参数事件监听器。
///
/// 需要被注销的事件处理方法。
- public void UnRegister(Action onEvent) => _mOnEvent -= onEvent;
+ public void UnRegister(Action onEvent)
+ {
+ _mOnEvent -= onEvent;
+ }
///
- /// 触发所有已注册的事件处理程序,并传递参数 t、k 和 s。
+ /// 触发所有已注册的事件处理程序,并传递参数 t、k 和 s。
///
/// 第一个参数。
/// 第二个参数。
/// 第三个参数。
- public void Trigger(T t, TK k, TS s) => _mOnEvent?.Invoke(t, k, s);
-
- ///
- /// 显式实现 IEasyEvent 接口中的 Register 方法。
- /// 允许使用无参 Action 来订阅当前带参事件。
- ///
- /// 无参事件处理方法。
- /// IUnRegister 对象,用于稍后注销该事件监听器。
- IUnRegister IEasyEvent.Register(Action onEvent)
+ public void Trigger(T t, TK k, TS s)
{
- return Register(Action);
- void Action(T _, TK __, TS ___) => onEvent();
+ _mOnEvent?.Invoke(t, k, s);
}
-}
+}
\ No newline at end of file
diff --git a/GFramework.Core/events/EasyEvents.cs b/GFramework.Core/events/EasyEvents.cs
index 6d2b00e..32d979c 100644
--- a/GFramework.Core/events/EasyEvents.cs
+++ b/GFramework.Core/events/EasyEvents.cs
@@ -1,42 +1,51 @@
namespace GFramework.Core.events;
///
-/// EasyEvents事件管理器类,用于全局事件的注册、获取和管理
-/// 提供了类型安全的事件系统,支持泛型事件的自动创建和检索
+/// EasyEvents事件管理器类,用于全局事件的注册、获取和管理
+/// 提供了类型安全的事件系统,支持泛型事件的自动创建和检索
///
public class EasyEvents
{
///
- /// 全局单例事件管理器实例
+ /// 全局单例事件管理器实例
///
private static readonly EasyEvents MGlobalEvents = new();
///
- /// 获取指定类型的全局事件实例
- ///
- /// 事件类型,必须实现IEasyEvent接口
- /// 指定类型的事件实例,如果未注册则返回默认值
- public static T Get() where T : IEasyEvent => MGlobalEvents.GetEvent();
-
- ///
- /// 注册指定类型的全局事件
- ///
- /// 事件类型,必须实现IEasyEvent接口且具有无参构造函数
- public static void Register() where T : IEasyEvent, new() => MGlobalEvents.AddEvent();
-
- ///
- /// 存储事件类型与事件实例映射关系的字典
+ /// 存储事件类型与事件实例映射关系的字典
///
private readonly Dictionary _mTypeEvents = new();
///
- /// 添加指定类型的事件到事件字典中
+ /// 获取指定类型的全局事件实例
///
- /// 事件类型,必须实现IEasyEvent接口且具有无参构造函数
- public void AddEvent() where T : IEasyEvent, new() => _mTypeEvents.Add(typeof(T), new T());
+ /// 事件类型,必须实现IEasyEvent接口
+ /// 指定类型的事件实例,如果未注册则返回默认值
+ public static T Get() where T : IEasyEvent
+ {
+ return MGlobalEvents.GetEvent();
+ }
///
- /// 获取指定类型的事件实例
+ /// 注册指定类型的全局事件
+ ///
+ /// 事件类型,必须实现IEasyEvent接口且具有无参构造函数
+ public static void Register() where T : IEasyEvent, new()
+ {
+ MGlobalEvents.AddEvent();
+ }
+
+ ///
+ /// 添加指定类型的事件到事件字典中
+ ///
+ /// 事件类型,必须实现IEasyEvent接口且具有无参构造函数
+ public void AddEvent() where T : IEasyEvent, new()
+ {
+ _mTypeEvents.Add(typeof(T), new T());
+ }
+
+ ///
+ /// 获取指定类型的事件实例
///
/// 事件类型,必须实现IEasyEvent接口
/// 指定类型的事件实例,如果不存在则返回默认值
@@ -46,7 +55,7 @@ public class EasyEvents
}
///
- /// 获取指定类型的事件实例,如果不存在则创建并添加到事件字典中
+ /// 获取指定类型的事件实例,如果不存在则创建并添加到事件字典中
///
/// 事件类型,必须实现IEasyEvent接口且具有无参构造函数
/// 指定类型的事件实例
@@ -54,14 +63,11 @@ public class EasyEvents
{
var eType = typeof(T);
// 尝试从字典中获取事件实例
- if (_mTypeEvents.TryGetValue(eType, out var e))
- {
- return (T)e;
- }
+ if (_mTypeEvents.TryGetValue(eType, out var e)) return (T)e;
// 如果不存在则创建新实例并添加到字典中
var t = new T();
_mTypeEvents.Add(eType, t);
return t;
}
-}
+}
\ No newline at end of file
diff --git a/GFramework.Core/events/ICanRegisterEvent.cs b/GFramework.Core/events/ICanRegisterEvent.cs
index f3fc0e5..4f81c32 100644
--- a/GFramework.Core/events/ICanRegisterEvent.cs
+++ b/GFramework.Core/events/ICanRegisterEvent.cs
@@ -3,8 +3,8 @@ using GFramework.Core.rule;
namespace GFramework.Core.events;
///
-/// 定义一个可以注册事件的接口,继承自IBelongToArchitecture接口。
-/// 该接口用于标识那些能够注册事件的对象,通常在框架的事件系统中使用。
-/// 实现此接口的类型表明它属于某个架构组件,并具备事件注册的能力。
+/// 定义一个可以注册事件的接口,继承自IBelongToArchitecture接口。
+/// 该接口用于标识那些能够注册事件的对象,通常在框架的事件系统中使用。
+/// 实现此接口的类型表明它属于某个架构组件,并具备事件注册的能力。
///
-public interface ICanRegisterEvent:IBelongToArchitecture;
+public interface ICanRegisterEvent : IBelongToArchitecture;
\ No newline at end of file
diff --git a/GFramework.Core/events/ICanSendEvent.cs b/GFramework.Core/events/ICanSendEvent.cs
index 26a0b86..0710c4e 100644
--- a/GFramework.Core/events/ICanSendEvent.cs
+++ b/GFramework.Core/events/ICanSendEvent.cs
@@ -3,7 +3,7 @@ using GFramework.Core.rule;
namespace GFramework.Core.events;
///
-/// 定义一个可以发送事件的接口,继承自IBelongToArchitecture接口。
-/// 该接口用于标识那些具备发送事件能力的类型,通常作为架构中事件发送功能的基础接口。
+/// 定义一个可以发送事件的接口,继承自IBelongToArchitecture接口。
+/// 该接口用于标识那些具备发送事件能力的类型,通常作为架构中事件发送功能的基础接口。
///
-public interface ICanSendEvent : IBelongToArchitecture;
+public interface ICanSendEvent : IBelongToArchitecture;
\ No newline at end of file
diff --git a/GFramework.Core/events/IEasyEvent.cs b/GFramework.Core/events/IEasyEvent.cs
index 1fdac52..ce4dd3d 100644
--- a/GFramework.Core/events/IEasyEvent.cs
+++ b/GFramework.Core/events/IEasyEvent.cs
@@ -1,12 +1,12 @@
namespace GFramework.Core.events;
///
-/// 事件接口,定义了事件注册的基本功能
+/// 事件接口,定义了事件注册的基本功能
///
public interface IEasyEvent
{
///
- /// 注册事件处理函数
+ /// 注册事件处理函数
///
/// 事件触发时要执行的回调函数
/// 用于取消注册的句柄对象
diff --git a/GFramework.Core/events/IUnRegister.cs b/GFramework.Core/events/IUnRegister.cs
index 3498702..a086e8b 100644
--- a/GFramework.Core/events/IUnRegister.cs
+++ b/GFramework.Core/events/IUnRegister.cs
@@ -1,12 +1,12 @@
namespace GFramework.Core.events;
///
-/// 提供注销功能的接口
+/// 提供注销功能的接口
///
public interface IUnRegister
{
///
- /// 执行注销操作
+ /// 执行注销操作
///
void UnRegister();
-}
+}
\ No newline at end of file
diff --git a/GFramework.Core/events/IUnRegisterList.cs b/GFramework.Core/events/IUnRegisterList.cs
index 35869b4..3edbc88 100644
--- a/GFramework.Core/events/IUnRegisterList.cs
+++ b/GFramework.Core/events/IUnRegisterList.cs
@@ -1,12 +1,12 @@
namespace GFramework.Core.events;
///
-/// 提供统一注销功能的接口,用于管理需要注销的对象列表
+/// 提供统一注销功能的接口,用于管理需要注销的对象列表
///
public interface IUnRegisterList
{
///
- /// 获取需要注销的对象列表
+ /// 获取需要注销的对象列表
///
List UnregisterList { get; }
-}
+}
\ No newline at end of file
diff --git a/GFramework.Core/events/OrEvent.cs b/GFramework.Core/events/OrEvent.cs
index db46a8a..2744693 100644
--- a/GFramework.Core/events/OrEvent.cs
+++ b/GFramework.Core/events/OrEvent.cs
@@ -3,12 +3,19 @@ using GFramework.Core.extensions;
namespace GFramework.Core.events;
///
-/// OrEvent类用于实现事件的或逻辑组合,当任意一个注册的事件触发时,都会触发OrEvent本身
+/// OrEvent类用于实现事件的或逻辑组合,当任意一个注册的事件触发时,都会触发OrEvent本身
///
public class OrEvent : IUnRegisterList
{
+ private Action _mOnEvent = () => { };
+
///
- /// 将指定的事件与当前OrEvent进行或逻辑组合
+ /// 获取取消注册列表
+ ///
+ public List UnregisterList { get; } = new();
+
+ ///
+ /// 将指定的事件与当前OrEvent进行或逻辑组合
///
/// 要组合的事件对象
/// 返回当前OrEvent实例,支持链式调用
@@ -18,10 +25,8 @@ public class OrEvent : IUnRegisterList
return this;
}
- private Action _mOnEvent = () => { };
-
///
- /// 注册事件处理函数
+ /// 注册事件处理函数
///
/// 要注册的事件处理函数
/// 返回一个可取消注册的对象
@@ -32,7 +37,7 @@ public class OrEvent : IUnRegisterList
}
///
- /// 取消注册指定的事件处理函数
+ /// 取消注册指定的事件处理函数
///
/// 要取消注册的事件处理函数
public void UnRegister(Action onEvent)
@@ -42,12 +47,10 @@ public class OrEvent : IUnRegisterList
}
///
- /// 触发所有已注册的事件处理函数
+ /// 触发所有已注册的事件处理函数
///
- private void Trigger() => _mOnEvent?.Invoke();
-
- ///
- /// 获取取消注册列表
- ///
- public List UnregisterList { get; } = new List();
-}
+ private void Trigger()
+ {
+ _mOnEvent?.Invoke();
+ }
+}
\ No newline at end of file
diff --git a/GFramework.Core/events/README.md b/GFramework.Core/events/README.md
index 2b03473..80651d6 100644
--- a/GFramework.Core/events/README.md
+++ b/GFramework.Core/events/README.md
@@ -11,6 +11,7 @@ Events 包提供了一套完整的事件系统,实现了观察者模式(Obse
基础事件接口,定义了事件注册的基本功能。
**核心方法:**
+
```csharp
IUnRegister Register(Action onEvent); // 注册事件处理函数
```
@@ -20,6 +21,7 @@ IUnRegister Register(Action onEvent); // 注册事件处理函数
注销接口,用于取消事件注册。
**核心方法:**
+
```csharp
void UnRegister(); // 执行注销操作
```
@@ -29,6 +31,7 @@ void UnRegister(); // 执行注销操作
注销列表接口,用于批量管理注销对象。
**属性:**
+
```csharp
List UnregisterList { get; } // 获取注销列表
```
@@ -456,42 +459,42 @@ public override void _Ready()
## 最佳实践
1. **事件命名规范**
- - 使用过去式:`PlayerDiedEvent`、`LevelCompletedEvent`
- - 使用 `Event` 后缀:便于识别
- - 使用结构体:减少内存分配
+ - 使用过去式:`PlayerDiedEvent`、`LevelCompletedEvent`
+ - 使用 `Event` 后缀:便于识别
+ - 使用结构体:减少内存分配
2. **事件数据设计**
- - 只包含必要信息
- - 使用值类型(struct)提高性能
- - 避免传递可变引用
+ - 只包含必要信息
+ - 使用值类型(struct)提高性能
+ - 避免传递可变引用
3. **避免事件循环**
- - 事件处理器中谨慎发送新事件
- - 使用命令打破循环依赖
+ - 事件处理器中谨慎发送新事件
+ - 使用命令打破循环依赖
4. **合理使用事件**
- - 用于通知状态变化
- - 用于跨模块通信
- - 不用于返回数据(使用 Query)
+ - 用于通知状态变化
+ - 用于跨模块通信
+ - 不用于返回数据(使用 Query)
5. **注销管理**
- - 始终注销事件监听
- - 使用 `IUnRegisterList` 批量管理
- - 利用 Godot 节点生命周期
+ - 始终注销事件监听
+ - 使用 `IUnRegisterList` 批量管理
+ - 利用 Godot 节点生命周期
6. **性能考虑**
- - 避免频繁触发的事件(如每帧)
- - 事件处理器保持轻量
- - 使用结构体事件减少 GC
+ - 避免频繁触发的事件(如每帧)
+ - 事件处理器保持轻量
+ - 使用结构体事件减少 GC
## 事件 vs 其他通信方式
-| 方式 | 适用场景 | 优点 | 缺点 |
-|------|---------|------|------|
-| **Event** | 状态变化通知、跨模块通信 | 松耦合、一对多 | 难以追踪调用链 |
-| **Command** | 执行操作、修改状态 | 封装逻辑、可撤销 | 单向通信 |
-| **Query** | 查询数据 | 职责清晰、有返回值 | 同步调用 |
-| **BindableProperty** | UI 数据绑定 | 自动更新、响应式 | 仅限单一属性 |
+| 方式 | 适用场景 | 优点 | 缺点 |
+|----------------------|--------------|-----------|---------|
+| **Event** | 状态变化通知、跨模块通信 | 松耦合、一对多 | 难以追踪调用链 |
+| **Command** | 执行操作、修改状态 | 封装逻辑、可撤销 | 单向通信 |
+| **Query** | 查询数据 | 职责清晰、有返回值 | 同步调用 |
+| **BindableProperty** | UI 数据绑定 | 自动更新、响应式 | 仅限单一属性 |
## 相关包
diff --git a/GFramework.Core/events/TypeEventSystem.cs b/GFramework.Core/events/TypeEventSystem.cs
index 287a83c..6ffbb0f 100644
--- a/GFramework.Core/events/TypeEventSystem.cs
+++ b/GFramework.Core/events/TypeEventSystem.cs
@@ -1,19 +1,27 @@
namespace GFramework.Core.events;
///
-/// TypeEventSystem
+/// TypeEventSystem
///
public class TypeEventSystem
{
+ public static readonly TypeEventSystem Global = new();
private readonly EasyEvents _mEvents = new();
- public static readonly TypeEventSystem Global = new();
+ public void Send() where T : new()
+ {
+ _mEvents.GetEvent>()?.Trigger(new T());
+ }
- public void Send() where T : new() => _mEvents.GetEvent>()?.Trigger(new T());
+ public void Send(T e)
+ {
+ _mEvents.GetEvent>()?.Trigger(e);
+ }
- public void Send(T e) => _mEvents.GetEvent>()?.Trigger(e);
-
- public IUnRegister Register(Action onEvent) => _mEvents.GetOrAddEvent>().Register(onEvent);
+ public IUnRegister Register(Action onEvent)
+ {
+ return _mEvents.GetOrAddEvent>().Register(onEvent);
+ }
public void UnRegister(Action onEvent)
{
diff --git a/GFramework.Core/events/UnRegisterList.cs b/GFramework.Core/events/UnRegisterList.cs
index f5c4b8c..c1bf0b0 100644
--- a/GFramework.Core/events/UnRegisterList.cs
+++ b/GFramework.Core/events/UnRegisterList.cs
@@ -1,15 +1,19 @@
namespace GFramework.Core.events;
-
///
-/// 取消注册列表类,用于管理多个需要取消注册的对象
+/// 取消注册列表类,用于管理多个需要取消注册的对象
///
public class UnRegisterList : IUnRegisterList
{
private readonly List _unRegisterList = [];
///
- /// 向取消注册列表中添加一个新的可取消注册对象
+ /// 获取取消注册列表的只读属性
+ ///
+ public List UnregisterList { get; }
+
+ ///
+ /// 向取消注册列表中添加一个新的可取消注册对象
///
/// 需要添加到列表中的可取消注册对象
public void Add(IUnRegister unRegister)
@@ -18,22 +22,14 @@ public class UnRegisterList : IUnRegisterList
}
///
- /// 对列表中的所有对象执行取消注册操作,并清空列表
+ /// 对列表中的所有对象执行取消注册操作,并清空列表
///
public void UnRegisterAll()
{
// 遍历所有注册项并执行取消注册
- foreach (var t in _unRegisterList)
- {
- t.UnRegister();
- }
+ foreach (var t in _unRegisterList) t.UnRegister();
// 清空列表
_unRegisterList.Clear();
}
-
- ///
- /// 获取取消注册列表的只读属性
- ///
- public List UnregisterList { get; }
-}
+}
\ No newline at end of file
diff --git a/GFramework.Core/extensions/CanGetExtensions.cs b/GFramework.Core/extensions/CanGetExtensions.cs
index de0d448..335580c 100644
--- a/GFramework.Core/extensions/CanGetExtensions.cs
+++ b/GFramework.Core/extensions/CanGetExtensions.cs
@@ -5,46 +5,52 @@ using GFramework.Core.utility;
namespace GFramework.Core.extensions;
///
-/// 提供获取模型对象扩展方法的静态类
+/// 提供获取模型对象扩展方法的静态类
///
public static class CanGetModelExtension
{
///
- /// 从架构中获取指定类型的模型实例
+ /// 从架构中获取指定类型的模型实例
///
/// 要获取的模型类型,必须实现IModel接口
/// 实现ICanGetModel接口的对象实例
/// 指定类型的模型实例
- public static T GetModel(this ICanGetModel self) where T : class, IModel =>
- self.GetArchitecture().GetModel();
+ public static T GetModel(this ICanGetModel self) where T : class, IModel
+ {
+ return self.GetArchitecture().GetModel();
+ }
}
///
-/// 提供获取系统对象扩展方法的静态类
+/// 提供获取系统对象扩展方法的静态类
///
public static class CanGetSystemExtension
{
///
- /// 从架构中获取指定类型的系统实例
+ /// 从架构中获取指定类型的系统实例
///
/// 要获取的系统类型,必须实现ISystem接口
/// 实现ICanGetSystem接口的对象实例
/// 指定类型的系统实例
- public static T GetSystem(this ICanGetSystem self) where T : class, ISystem =>
- self.GetArchitecture().GetSystem();
+ public static T GetSystem(this ICanGetSystem self) where T : class, ISystem
+ {
+ return self.GetArchitecture().GetSystem();
+ }
}
///
-/// 提供获取工具对象扩展方法的静态类
+/// 提供获取工具对象扩展方法的静态类
///
public static class CanGetUtilityExtension
{
///
- /// 从架构中获取指定类型的工具实例
+ /// 从架构中获取指定类型的工具实例
///
/// 要获取的工具类型,必须实现IUtility接口
/// 实现ICanGetUtility接口的对象实例
/// 指定类型的工具实例
- public static T GetUtility(this ICanGetUtility self) where T : class, IUtility =>
- self.GetArchitecture().GetUtility();
+ public static T GetUtility(this ICanGetUtility self) where T : class, IUtility
+ {
+ return self.GetArchitecture().GetUtility();
+ }
}
\ No newline at end of file
diff --git a/GFramework.Core/extensions/CanRegisterEventExtensions.cs b/GFramework.Core/extensions/CanRegisterEventExtensions.cs
index b3a13d6..e059a62 100644
--- a/GFramework.Core/extensions/CanRegisterEventExtensions.cs
+++ b/GFramework.Core/extensions/CanRegisterEventExtensions.cs
@@ -3,26 +3,30 @@
namespace GFramework.Core.extensions;
///
-/// 事件注册扩展类,提供ICanRegisterEvent接口的扩展方法用于注册和注销事件
+/// 事件注册扩展类,提供ICanRegisterEvent接口的扩展方法用于注册和注销事件
///
public static class CanRegisterEventExtensions
{
///
- /// 注册指定类型的事件处理函数
+ /// 注册指定类型的事件处理函数
///
/// 事件数据类型
/// 实现ICanRegisterEvent接口的对象实例
/// 事件处理回调函数
/// 返回事件注销器接口,可用于后续注销事件
- public static IUnRegister RegisterEvent(this ICanRegisterEvent self, Action onEvent) =>
- self.GetArchitecture().RegisterEvent(onEvent);
+ public static IUnRegister RegisterEvent(this ICanRegisterEvent self, Action onEvent)
+ {
+ return self.GetArchitecture().RegisterEvent(onEvent);
+ }
///
- /// 注销指定类型的事件处理函数
+ /// 注销指定类型的事件处理函数
///
/// 事件数据类型
/// 实现ICanRegisterEvent接口的对象实例
/// 要注销的事件处理回调函数
- public static void UnRegisterEvent(this ICanRegisterEvent self, Action onEvent) =>
+ public static void UnRegisterEvent(this ICanRegisterEvent self, Action onEvent)
+ {
self.GetArchitecture().UnRegisterEvent(onEvent);
-}
+ }
+}
\ No newline at end of file
diff --git a/GFramework.Core/extensions/CanSendExtensions.cs b/GFramework.Core/extensions/CanSendExtensions.cs
index 2e4b78b..f72c216 100644
--- a/GFramework.Core/extensions/CanSendExtensions.cs
+++ b/GFramework.Core/extensions/CanSendExtensions.cs
@@ -5,72 +5,85 @@ using GFramework.Core.query;
namespace GFramework.Core.extensions;
///
-/// 提供发送命令功能的扩展类
+/// 提供发送命令功能的扩展类
///
public static class CanSendCommandExtension
{
///
- /// 发送指定类型的命令,该命令类型必须实现ICommand接口且具有无参构造函数
+ /// 发送指定类型的命令,该命令类型必须实现ICommand接口且具有无参构造函数
///
/// 命令类型,必须实现ICommand接口且具有无参构造函数
/// 实现ICanSendCommand接口的对象实例
- public static void SendCommand(this ICanSendCommand self) where T : ICommand, new() =>
+ public static void SendCommand(this ICanSendCommand self) where T : ICommand, new()
+ {
self.GetArchitecture().SendCommand(new T());
+ }
///
- /// 发送指定的命令实例
+ /// 发送指定的命令实例
///
/// 命令类型,必须实现ICommand接口
/// 实现ICanSendCommand接口的对象实例
/// 要发送的命令实例
- public static void SendCommand(this ICanSendCommand self, T command) where T : ICommand =>
+ public static void SendCommand(this ICanSendCommand self, T command) where T : ICommand
+ {
self.GetArchitecture().SendCommand(command);
+ }
///
- /// 发送带有返回值的命令并获取执行结果
+ /// 发送带有返回值的命令并获取执行结果
///
/// 命令执行结果的类型
/// 实现ICanSendCommand接口的对象实例
/// 要发送的命令实例,必须实现ICommand<TResult>接口
/// 命令执行后的返回结果
- public static TResult SendCommand(this ICanSendCommand self, ICommand command) =>
- self.GetArchitecture().SendCommand(command);
+ public static TResult SendCommand(this ICanSendCommand self, ICommand command)
+ {
+ return self.GetArchitecture().SendCommand(command);
+ }
}
///
-/// 提供发送事件功能的扩展类
+/// 提供发送事件功能的扩展类
///
public static class CanSendEventExtension
{
///
- /// 发送指定类型的事件,该事件类型必须具有无参构造函数
+ /// 发送指定类型的事件,该事件类型必须具有无参构造函数
///
/// 事件类型,必须具有无参构造函数
/// 实现ICanSendEvent接口的对象实例
- public static void SendEvent(this ICanSendEvent self) where T : new() =>
+ public static void SendEvent(this ICanSendEvent self) where T : new()
+ {
self.GetArchitecture().SendEvent();
+ }
///
- /// 发送指定的事件实例
+ /// 发送指定的事件实例
///
/// 事件类型
/// 实现ICanSendEvent接口的对象实例
/// 要发送的事件实例
- public static void SendEvent(this ICanSendEvent self, T e) => self.GetArchitecture().SendEvent(e);
+ public static void SendEvent(this ICanSendEvent self, T e)
+ {
+ self.GetArchitecture().SendEvent(e);
+ }
}
///
-/// 提供发送查询功能的扩展类
+/// 提供发送查询功能的扩展类
///
public static class CanSendQueryExtension
{
///
- /// 发送查询请求并获取查询结果
+ /// 发送查询请求并获取查询结果
///
/// 查询结果的类型
/// 实现ICanSendQuery接口的对象实例
/// 要发送的查询实例,必须实现IQuery<TResult>接口
/// 查询操作的返回结果
- public static TResult SendQuery(this ICanSendQuery self, IQuery query) =>
- self.GetArchitecture().SendQuery(query);
-}
+ public static TResult SendQuery(this ICanSendQuery self, IQuery query)
+ {
+ return self.GetArchitecture().SendQuery(query);
+ }
+}
\ No newline at end of file
diff --git a/GFramework.Core/extensions/OrEventExtensions.cs b/GFramework.Core/extensions/OrEventExtensions.cs
index b61bdda..49a880f 100644
--- a/GFramework.Core/extensions/OrEventExtensions.cs
+++ b/GFramework.Core/extensions/OrEventExtensions.cs
@@ -3,15 +3,18 @@
namespace GFramework.Core.extensions;
///
-/// 提供Or事件扩展方法的静态类
+/// 提供Or事件扩展方法的静态类
///
public static class OrEventExtensions
{
///
- /// 创建一个OrEvent实例,将当前事件与指定事件进行逻辑或运算组合
+ /// 创建一个OrEvent实例,将当前事件与指定事件进行逻辑或运算组合
///
/// 当前的IEasyEvent事件实例
/// 要与当前事件进行或运算的另一个IEasyEvent事件实例
/// 返回一个新的OrEvent实例,表示两个事件的或运算结果
- public static OrEvent Or(this IEasyEvent self, IEasyEvent e) => new OrEvent().Or(self).Or(e);
+ public static OrEvent Or(this IEasyEvent self, IEasyEvent e)
+ {
+ return new OrEvent().Or(self).Or(e);
+ }
}
\ No newline at end of file
diff --git a/GFramework.Core/extensions/README.md b/GFramework.Core/extensions/README.md
index dad7ab7..0bb2144 100644
--- a/GFramework.Core/extensions/README.md
+++ b/GFramework.Core/extensions/README.md
@@ -8,7 +8,8 @@ Extensions 包提供了一系列扩展方法,简化了框架各个接口的使
### 1. 获取组件扩展 ([`CanGetExtensions.cs`](CanGetExtensions.cs))
-为 [`ICanGetModel`](../model/ICanGetModel.cs)、[`ICanGetSystem`](../system/ICanGetSystem.cs)、[`ICanGetUtility`](../utility/ICanGetUtility.cs) 提供扩展方法。
+为 [`ICanGetModel`](../model/ICanGetModel.cs)、[`ICanGetSystem`](../system/ICanGetSystem.cs)、[
+`ICanGetUtility`](../utility/ICanGetUtility.cs) 提供扩展方法。
#### CanGetModelExtension
@@ -480,17 +481,17 @@ public class AchievementSystem : AbstractSystem
```
2. **理解扩展方法本质**:
- - 扩展方法是静态方法的语法糖
- - 不会改变原始类型的结构
- - 仅在编译时解析
+ - 扩展方法是静态方法的语法糖
+ - 不会改变原始类型的结构
+ - 仅在编译时解析
3. **Godot 特定功能**:
- - `UnRegisterWhenNodeExitTree` 仅在 Godot 环境下可用
- - 使用 `#if GODOT` 编译指令控制
+ - `UnRegisterWhenNodeExitTree` 仅在 Godot 环境下可用
+ - 使用 `#if GODOT` 编译指令控制
4. **性能考虑**:
- - 扩展方法本身无性能开销
- - 实际调用的是底层方法
+ - 扩展方法本身无性能开销
+ - 实际调用的是底层方法
## 相关包
diff --git a/GFramework.Core/extensions/UnRegisterListExtension.cs b/GFramework.Core/extensions/UnRegisterListExtension.cs
index c0ef67d..6a0a56d 100644
--- a/GFramework.Core/extensions/UnRegisterListExtension.cs
+++ b/GFramework.Core/extensions/UnRegisterListExtension.cs
@@ -2,33 +2,31 @@
namespace GFramework.Core.extensions;
-
///
-/// 扩展方法类,为IUnRegister和IUnRegisterList接口提供便捷的注册和注销功能
+/// 扩展方法类,为IUnRegister和IUnRegisterList接口提供便捷的注册和注销功能
///
public static class UnRegisterListExtension
{
///
- /// 将指定的可注销对象添加到注销列表中
+ /// 将指定的可注销对象添加到注销列表中
///
/// 要添加的可注销对象
/// 目标注销列表
- public static void AddToUnregisterList(this IUnRegister self, IUnRegisterList unRegisterList) =>
+ public static void AddToUnregisterList(this IUnRegister self, IUnRegisterList unRegisterList)
+ {
unRegisterList.UnregisterList.Add(self);
+ }
///
- /// 注销列表中的所有对象并清空列表
+ /// 注销列表中的所有对象并清空列表
///
/// 包含注销列表的对象
public static void UnRegisterAll(this IUnRegisterList self)
{
// 遍历注销列表中的所有对象并执行注销操作
- foreach (var unRegister in self.UnregisterList)
- {
- unRegister.UnRegister();
- }
+ foreach (var unRegister in self.UnregisterList) unRegister.UnRegister();
// 清空注销列表
self.UnregisterList.Clear();
}
-}
+}
\ No newline at end of file
diff --git a/GFramework.Core/ioc/IocContainer.cs b/GFramework.Core/ioc/IocContainer.cs
index fa92113..824abcc 100644
--- a/GFramework.Core/ioc/IocContainer.cs
+++ b/GFramework.Core/ioc/IocContainer.cs
@@ -1,14 +1,14 @@
namespace GFramework.Core.ioc;
///
-/// IOC容器类,用于管理对象的注册和获取
+/// IOC容器类,用于管理对象的注册和获取
///
public class IocContainer
{
private readonly Dictionary _mInstances = new();
///
- /// 注册一个实例到IOC容器中
+ /// 注册一个实例到IOC容器中
///
/// 实例的类型
/// 要注册的实例对象
@@ -20,7 +20,7 @@ public class IocContainer
}
///
- /// 从IOC容器中获取指定类型的实例
+ /// 从IOC容器中获取指定类型的实例
///
/// 要获取的实例类型
/// 返回指定类型的实例,如果未找到则返回null
@@ -29,11 +29,8 @@ public class IocContainer
var key = typeof(T);
// 尝试从字典中获取实例
- if (_mInstances.TryGetValue(key, out var retInstance))
- {
- return retInstance as T;
- }
+ if (_mInstances.TryGetValue(key, out var retInstance)) return retInstance as T;
return null;
}
-}
+}
\ No newline at end of file
diff --git a/GFramework.Core/ioc/README.md b/GFramework.Core/ioc/README.md
index b70c6fc..00a89d9 100644
--- a/GFramework.Core/ioc/README.md
+++ b/GFramework.Core/ioc/README.md
@@ -2,7 +2,8 @@
## 概述
-IoC(Inversion of Control,控制反转)包提供了一个轻量级的依赖注入容器,用于管理框架中各种组件的注册和获取。通过 IoC 容器,可以实现组件间的解耦,便于测试和维护。
+IoC(Inversion of Control,控制反转)包提供了一个轻量级的依赖注入容器,用于管理框架中各种组件的注册和获取。通过 IoC
+容器,可以实现组件间的解耦,便于测试和维护。
## 核心类
@@ -11,6 +12,7 @@ IoC(Inversion of Control,控制反转)包提供了一个轻量级的依赖
IoC 容器类,负责管理对象的注册和获取。
**主要功能:**
+
- 注册实例到容器
- 从容器中获取实例
- 类型安全的依赖管理
@@ -26,6 +28,7 @@ public void Register(T instance)
```
**参数:**
+
- `instance`: 要注册的实例对象
**使用示例:**
@@ -48,6 +51,7 @@ public T Get() where T : class
```
**返回值:**
+
- 返回指定类型的实例,如果未找到则返回 `null`
**使用示例:**
@@ -294,6 +298,7 @@ var service = container.Get();
```
**特点:**
+
- ✅ 简单易用
- ✅ 性能高
- ❌ 不支持构造函数注入
@@ -314,6 +319,7 @@ var controller = container.Resolve();
```
**特点:**
+
- ✅ 自动依赖注入
- ✅ 生命周期管理
- ✅ 复杂场景支持
@@ -391,20 +397,20 @@ else
## 注意事项
1. **类型唯一性**
- - 每个类型只能注册一个实例
- - 重复注册会覆盖之前的实例
+ - 每个类型只能注册一个实例
+ - 重复注册会覆盖之前的实例
2. **手动管理依赖顺序**
- - 组件的依赖关系需要手动保证
- - 先注册被依赖的组件
+ - 组件的依赖关系需要手动保证
+ - 先注册被依赖的组件
3. **无生命周期管理**
- - 实例一旦注册就一直存在
- - 需要手动管理实例的生命周期
+ - 实例一旦注册就一直存在
+ - 需要手动管理实例的生命周期
4. **线程安全**
- - 当前实现非线程安全
- - 避免多线程同时访问
+ - 当前实现非线程安全
+ - 避免多线程同时访问
## 扩展可能性
diff --git a/GFramework.Core/model/AbstractModel.cs b/GFramework.Core/model/AbstractModel.cs
index 99ced7a..b34b932 100644
--- a/GFramework.Core/model/AbstractModel.cs
+++ b/GFramework.Core/model/AbstractModel.cs
@@ -3,34 +3,43 @@
namespace GFramework.Core.model;
///
-/// 抽象模型基类,实现IModel接口,提供模型的基本架构支持
+/// 抽象模型基类,实现IModel接口,提供模型的基本架构支持
///
public abstract class AbstractModel : IModel
{
///
- /// 模型所属的架构实例
+ /// 模型所属的架构实例
///
protected IArchitecture Architecture;
///
- /// 获取模型所属的架构实例
+ /// 获取模型所属的架构实例
///
/// 返回当前模型关联的架构对象
- public IArchitecture GetArchitecture() => Architecture;
+ public IArchitecture GetArchitecture()
+ {
+ return Architecture;
+ }
///
- /// 设置模型所属的架构实例
+ /// 设置模型所属的架构实例
///
/// 要关联到此模型的架构实例
- public void SetArchitecture(IArchitecture architecture) => Architecture = architecture;
+ public void SetArchitecture(IArchitecture architecture)
+ {
+ Architecture = architecture;
+ }
///
- /// 初始化模型,调用抽象方法OnInit执行具体初始化逻辑
+ /// 初始化模型,调用抽象方法OnInit执行具体初始化逻辑
///
- void IModel.Init() => OnInit();
+ void IModel.Init()
+ {
+ OnInit();
+ }
///
- /// 抽象初始化方法,由子类实现具体的初始化逻辑
+ /// 抽象初始化方法,由子类实现具体的初始化逻辑
///
protected abstract void OnInit();
-}
+}
\ No newline at end of file
diff --git a/GFramework.Core/model/ICanGetModel.cs b/GFramework.Core/model/ICanGetModel.cs
index b038882..5f1215c 100644
--- a/GFramework.Core/model/ICanGetModel.cs
+++ b/GFramework.Core/model/ICanGetModel.cs
@@ -3,7 +3,7 @@
namespace GFramework.Core.model;
///
-/// 定义一个接口,表示可以获取模型的架构组件。
-/// 该接口继承自IBelongToArchitecture,表明实现此接口的类型属于特定架构。
+/// 定义一个接口,表示可以获取模型的架构组件。
+/// 该接口继承自IBelongToArchitecture,表明实现此接口的类型属于特定架构。
///
-public interface ICanGetModel : IBelongToArchitecture;
+public interface ICanGetModel : IBelongToArchitecture;
\ No newline at end of file
diff --git a/GFramework.Core/model/IModel.cs b/GFramework.Core/model/IModel.cs
index a657b2b..fdde852 100644
--- a/GFramework.Core/model/IModel.cs
+++ b/GFramework.Core/model/IModel.cs
@@ -5,12 +5,12 @@ using GFramework.Core.utility;
namespace GFramework.Core.model;
///
-/// 模型接口,定义了模型的基本行为和功能
+/// 模型接口,定义了模型的基本行为和功能
///
public interface IModel : ICanSetArchitecture, ICanGetUtility, ICanSendEvent
{
///
- /// 初始化模型
+ /// 初始化模型
///
void Init();
-}
+}
\ No newline at end of file
diff --git a/GFramework.Core/model/README.md b/GFramework.Core/model/README.md
index 82461ae..92f5027 100644
--- a/GFramework.Core/model/README.md
+++ b/GFramework.Core/model/README.md
@@ -2,7 +2,8 @@
## 概述
-Model 包定义了数据模型层的接口和基类。Model 是 MVC 架构中的 M 层,负责管理应用程序的数据和状态。Model 层应该只包含数据和简单的数据逻辑,不包含复杂的业务逻辑。
+Model 包定义了数据模型层的接口和基类。Model 是 MVC 架构中的 M 层,负责管理应用程序的数据和状态。Model
+层应该只包含数据和简单的数据逻辑,不包含复杂的业务逻辑。
## 核心接口
@@ -11,11 +12,13 @@ Model 包定义了数据模型层的接口和基类。Model 是 MVC 架构中的
模型接口,定义了模型的基本行为和功能。
**继承的能力接口:**
+
- [`ICanSetArchitecture`](../rule/ICanSetArchitecture.cs) - 可设置架构引用
- [`ICanGetUtility`](../utility/ICanGetUtility.cs) - 可获取工具类
- [`ICanSendEvent`](../events/ICanSendEvent.cs) - 可发送事件
**核心方法:**
+
```csharp
void Init(); // 初始化模型
```
diff --git a/GFramework.Core/property/BindableProperty.cs b/GFramework.Core/property/BindableProperty.cs
index 0e4daba..6cac10b 100644
--- a/GFramework.Core/property/BindableProperty.cs
+++ b/GFramework.Core/property/BindableProperty.cs
@@ -2,34 +2,23 @@ using GFramework.Core.events;
namespace GFramework.Core.property;
-
///
-/// 可绑定属性类,用于实现数据绑定功能
+/// 可绑定属性类,用于实现数据绑定功能
///
/// 属性值的类型
/// 属性的默认值
public class BindableProperty(T defaultValue = default!) : IBindableProperty
{
+ private Action? _mOnValueChanged;
protected T MValue = defaultValue;
///
- /// 获取或设置属性值比较器,默认使用Equals方法进行比较
+ /// 获取或设置属性值比较器,默认使用Equals方法进行比较
///
public static Func Comparer { get; set; } = (a, b) => a!.Equals(b)!;
///
- /// 设置自定义比较器
- ///
- /// 用于比较两个值是否相等的函数
- /// 当前可绑定属性实例
- public BindableProperty WithComparer(Func comparer)
- {
- Comparer = comparer;
- return this;
- }
-
- ///
- /// 获取或设置属性值,当值发生变化时会触发注册的回调事件
+ /// 获取或设置属性值,当值发生变化时会触发注册的回调事件
///
public T Value
{
@@ -37,12 +26,12 @@ public class BindableProperty(T defaultValue = default!) : IBindableProperty<
set
{
// 使用 default(T) 替代 null 比较,避免 SonarQube 警告
- if (EqualityComparer.Default.Equals(value, default!) &&
- EqualityComparer.Default.Equals(MValue, default!))
+ if (EqualityComparer.Default.Equals(value, default!) &&
+ EqualityComparer.Default.Equals(MValue, default!))
return;
// 若新值与旧值相等则不执行后续操作
- if (!EqualityComparer.Default.Equals(value, default!) && Comparer(value, MValue))
+ if (!EqualityComparer.Default.Equals(value, default!) && Comparer(value, MValue))
return;
SetValue(value);
@@ -51,27 +40,16 @@ public class BindableProperty(T defaultValue = default!) : IBindableProperty<
}
///
- /// 设置属性值的虚方法,可在子类中重写
+ /// 直接设置属性值而不触发事件
///
/// 新的属性值
- protected virtual void SetValue(T newValue) => MValue = newValue;
+ public void SetValueWithoutEvent(T newValue)
+ {
+ MValue = newValue;
+ }
///
- /// 获取属性值的虚方法,可在子类中重写
- ///
- /// 当前属性值
- protected virtual T GetValue() => MValue;
-
- ///
- /// 直接设置属性值而不触发事件
- ///
- /// 新的属性值
- public void SetValueWithoutEvent(T newValue) => MValue = newValue;
-
- private Action? _mOnValueChanged = null;
-
- ///
- /// 注册属性值变化事件回调
+ /// 注册属性值变化事件回调
///
/// 属性值变化时的回调函数
/// 可用于取消注册的接口
@@ -82,7 +60,7 @@ public class BindableProperty(T defaultValue = default!) : IBindableProperty<
}
///
- /// 注册属性值变化事件回调,并立即调用回调函数传递当前值
+ /// 注册属性值变化事件回调,并立即调用回调函数传递当前值
///
/// 属性值变化时的回调函数
/// 可用于取消注册的接口
@@ -93,19 +71,23 @@ public class BindableProperty(T defaultValue = default!) : IBindableProperty<
}
///
- /// 取消注册属性值变化事件回调
+ /// 取消注册属性值变化事件回调
///
/// 要取消注册的回调函数
- public void UnRegister(Action onValueChanged) => _mOnValueChanged -= onValueChanged;
+ public void UnRegister(Action onValueChanged)
+ {
+ _mOnValueChanged -= onValueChanged;
+ }
///
- /// 实现IEasyEvent接口的注册方法,将无参事件转换为有参事件处理
+ /// 实现IEasyEvent接口的注册方法,将无参事件转换为有参事件处理
///
/// 无参事件回调
/// 可用于取消注册的接口
IUnRegister IEasyEvent.Register(Action onEvent)
{
return Register(Action);
+
void Action(T _)
{
onEvent();
@@ -113,8 +95,40 @@ public class BindableProperty(T defaultValue = default!) : IBindableProperty<
}
///
- /// 返回属性值的字符串表示形式
+ /// 设置自定义比较器
+ ///
+ /// 用于比较两个值是否相等的函数
+ /// 当前可绑定属性实例
+ public BindableProperty WithComparer(Func comparer)
+ {
+ Comparer = comparer;
+ return this;
+ }
+
+ ///
+ /// 设置属性值的虚方法,可在子类中重写
+ ///
+ /// 新的属性值
+ protected virtual void SetValue(T newValue)
+ {
+ MValue = newValue;
+ }
+
+ ///
+ /// 获取属性值的虚方法,可在子类中重写
+ ///
+ /// 当前属性值
+ protected virtual T GetValue()
+ {
+ return MValue;
+ }
+
+ ///
+ /// 返回属性值的字符串表示形式
///
/// 属性值的字符串表示
- public override string ToString() => Value?.ToString() ?? string.Empty;
+ public override string ToString()
+ {
+ return Value?.ToString() ?? string.Empty;
+ }
}
\ No newline at end of file
diff --git a/GFramework.Core/property/BindablePropertyUnRegister.cs b/GFramework.Core/property/BindablePropertyUnRegister.cs
index 7255b4a..b3526ad 100644
--- a/GFramework.Core/property/BindablePropertyUnRegister.cs
+++ b/GFramework.Core/property/BindablePropertyUnRegister.cs
@@ -2,9 +2,8 @@ using GFramework.Core.events;
namespace GFramework.Core.property;
-
///
-/// 可绑定属性注销器类,用于取消注册可绑定属性的值变化监听
+/// 可绑定属性注销器类,用于取消注册可绑定属性的值变化监听
///
/// 可绑定属性的值类型
/// 需要注销的可绑定属性实例
@@ -13,17 +12,17 @@ public class BindablePropertyUnRegister(BindableProperty bindableProperty,
: IUnRegister
{
///
- /// 获取或设置可绑定属性实例
+ /// 获取或设置可绑定属性实例
///
public BindableProperty BindableProperty { get; set; } = bindableProperty;
///
- /// 获取或设置值变化时的回调函数
+ /// 获取或设置值变化时的回调函数
///
public Action OnValueChanged { get; set; } = onValueChanged;
///
- /// 执行注销操作,取消注册值变化监听并清理引用
+ /// 执行注销操作,取消注册值变化监听并清理引用
///
public void UnRegister()
{
@@ -34,4 +33,4 @@ public class BindablePropertyUnRegister(BindableProperty bindableProperty,
// 清理回调函数引用
OnValueChanged = null;
}
-}
+}
\ No newline at end of file
diff --git a/GFramework.Core/property/IBindableProperty.cs b/GFramework.Core/property/IBindableProperty.cs
index c5a5a6e..68a659f 100644
--- a/GFramework.Core/property/IBindableProperty.cs
+++ b/GFramework.Core/property/IBindableProperty.cs
@@ -1,19 +1,19 @@
namespace GFramework.Core.property;
///
-/// 可绑定属性接口,继承自只读可绑定属性接口,提供可读写的属性绑定功能
+/// 可绑定属性接口,继承自只读可绑定属性接口,提供可读写的属性绑定功能
///
/// 属性值的类型
public interface IBindableProperty : IReadonlyBindableProperty
{
///
- /// 获取或设置属性的值
+ /// 获取或设置属性的值
///
new T Value { get; set; }
-
+
///
- /// 设置属性值但不触发事件通知
+ /// 设置属性值但不触发事件通知
///
/// 要设置的新值
void SetValueWithoutEvent(T newValue);
-}
+}
\ No newline at end of file
diff --git a/GFramework.Core/property/IReadonlyBindableProperty.cs b/GFramework.Core/property/IReadonlyBindableProperty.cs
index e99793e..a9fc3ad 100644
--- a/GFramework.Core/property/IReadonlyBindableProperty.cs
+++ b/GFramework.Core/property/IReadonlyBindableProperty.cs
@@ -2,35 +2,34 @@ using GFramework.Core.events;
namespace GFramework.Core.property;
-
///
-/// 只读可绑定属性接口,提供属性值的读取和变更监听功能
+/// 只读可绑定属性接口,提供属性值的读取和变更监听功能
///
/// 属性值的类型
public interface IReadonlyBindableProperty : IEasyEvent
{
///
- /// 获取属性的当前值
+ /// 获取属性的当前值
///
T Value { get; }
///
- /// 注册属性值变更回调,并立即执行一次初始值的回调
+ /// 注册属性值变更回调,并立即执行一次初始值的回调
///
/// 属性值变更时执行的回调函数,参数为新的属性值
/// 用于取消注册的句柄对象
IUnRegister RegisterWithInitValue(Action action);
-
+
///
- /// 取消注册属性值变更回调
+ /// 取消注册属性值变更回调
///
/// 要取消注册的回调函数
void UnRegister(Action onValueChanged);
-
+
///
- /// 注册属性值变更回调
+ /// 注册属性值变更回调
///
/// 属性值变更时执行的回调函数,参数为新的属性值
/// 用于取消注册的句柄对象
IUnRegister Register(Action onValueChanged);
-}
+}
\ No newline at end of file
diff --git a/GFramework.Core/property/README.md b/GFramework.Core/property/README.md
index 1f3db01..e9dc6f4 100644
--- a/GFramework.Core/property/README.md
+++ b/GFramework.Core/property/README.md
@@ -11,6 +11,7 @@ Property 包提供了可绑定属性(BindableProperty)的实现,支持属
只读可绑定属性接口,提供属性值的读取和变更监听功能。
**核心成员:**
+
```csharp
T Value { get; } // 获取属性值
IUnRegister Register(Action onValueChanged); // 注册监听
@@ -23,6 +24,7 @@ void UnRegister(Action onValueChanged); // 取消监听
可绑定属性接口,继承自只读接口,增加了修改能力。
**核心成员:**
+
```csharp
new T Value { get; set; } // 可读写的属性值
void SetValueWithoutEvent(T newValue); // 设置值但不触发事件
diff --git a/GFramework.Core/query/AbstractQuery.cs b/GFramework.Core/query/AbstractQuery.cs
index 2eba9f6..756c0d6 100644
--- a/GFramework.Core/query/AbstractQuery.cs
+++ b/GFramework.Core/query/AbstractQuery.cs
@@ -3,34 +3,43 @@ using GFramework.Core.architecture;
namespace GFramework.Core.query;
///
-/// 抽象查询类,提供查询操作的基础实现
+/// 抽象查询类,提供查询操作的基础实现
///
/// 查询结果的类型
public abstract class AbstractQuery : IQuery
{
- ///
- /// 执行查询操作
- ///
- /// 查询结果
- public T Do() => OnDo();
-
- ///
- /// 抽象方法,由子类实现具体的查询逻辑
- ///
- /// 查询结果
- protected abstract T OnDo();
-
private IArchitecture _mArchitecture;
///
- /// 获取架构实例
+ /// 执行查询操作
///
- /// 架构实例
- public IArchitecture GetArchitecture() => _mArchitecture;
+ /// 查询结果
+ public T Do()
+ {
+ return OnDo();
+ }
///
- /// 设置架构实例
+ /// 获取架构实例
+ ///
+ /// 架构实例
+ public IArchitecture GetArchitecture()
+ {
+ return _mArchitecture;
+ }
+
+ ///
+ /// 设置架构实例
///
/// 要设置的架构实例
- public void SetArchitecture(IArchitecture architecture) => _mArchitecture = architecture;
-}
+ public void SetArchitecture(IArchitecture architecture)
+ {
+ _mArchitecture = architecture;
+ }
+
+ ///
+ /// 抽象方法,由子类实现具体的查询逻辑
+ ///
+ /// 查询结果
+ protected abstract T OnDo();
+}
\ No newline at end of file
diff --git a/GFramework.Core/query/ICanSendQuery.cs b/GFramework.Core/query/ICanSendQuery.cs
index 291bdae..947c887 100644
--- a/GFramework.Core/query/ICanSendQuery.cs
+++ b/GFramework.Core/query/ICanSendQuery.cs
@@ -3,7 +3,7 @@ using GFramework.Core.rule;
namespace GFramework.Core.query;
///
-/// 定义一个可以发送查询的接口契约
-/// 该接口继承自IBelongToArchitecture,表示实现此接口的类型属于某个架构组件
+/// 定义一个可以发送查询的接口契约
+/// 该接口继承自IBelongToArchitecture,表示实现此接口的类型属于某个架构组件
///
-public interface ICanSendQuery : IBelongToArchitecture;
+public interface ICanSendQuery : IBelongToArchitecture;
\ No newline at end of file
diff --git a/GFramework.Core/query/IQuery.cs b/GFramework.Core/query/IQuery.cs
index 5170de5..f99ec0e 100644
--- a/GFramework.Core/query/IQuery.cs
+++ b/GFramework.Core/query/IQuery.cs
@@ -4,17 +4,16 @@ using GFramework.Core.system;
namespace GFramework.Core.query;
-
///
-/// 查询接口,定义了执行查询操作的契约
+/// 查询接口,定义了执行查询操作的契约
///
/// 查询结果的类型
public interface IQuery : ICanSetArchitecture, ICanGetModel, ICanGetSystem,
ICanSendQuery
{
///
- /// 执行查询操作并返回结果
+ /// 执行查询操作并返回结果
///
/// 查询的结果,类型为 TResult
TResult Do();
-}
+}
\ No newline at end of file
diff --git a/GFramework.Core/query/README.md b/GFramework.Core/query/README.md
index 9f8d849..aa53297 100644
--- a/GFramework.Core/query/README.md
+++ b/GFramework.Core/query/README.md
@@ -2,7 +2,8 @@
## 概述
-Query 包实现了 CQRS(命令查询职责分离)模式中的查询部分。Query 用于封装数据查询逻辑,与 Command 不同的是,Query 有返回值且不应该修改系统状态。
+Query 包实现了 CQRS(命令查询职责分离)模式中的查询部分。Query 用于封装数据查询逻辑,与 Command 不同的是,Query
+有返回值且不应该修改系统状态。
## 核心接口
@@ -11,6 +12,7 @@ Query 包实现了 CQRS(命令查询职责分离)模式中的查询部分。
标记接口,表示该类型可以发送查询。
**继承关系:**
+
```csharp
public interface ICanSendQuery : IBelongToArchitecture
```
@@ -20,11 +22,13 @@ public interface ICanSendQuery : IBelongToArchitecture
查询接口,定义了查询的基本契约。
**核心成员:**
+
```csharp
TResult Do(); // 执行查询并返回结果
```
**继承的能力:**
+
- `ICanSetArchitecture` - 可设置架构
- `ICanGetModel` - 可获取 Model
- `ICanGetSystem` - 可获取 System
@@ -37,6 +41,7 @@ TResult Do(); // 执行查询并返回结果
抽象查询基类,提供了查询的基础实现。
**使用方式:**
+
```csharp
public abstract class AbstractQuery : IQuery
{
@@ -287,11 +292,13 @@ public class EnemyAISystem : AbstractSystem
## Command vs Query
### Command(命令)
+
- **用途**:修改系统状态
- **返回值**:无返回值(void)
- **示例**:购买物品、造成伤害、升级角色
### Query(查询)
+
- **用途**:读取数据,不修改状态
- **返回值**:有返回值
- **示例**:获取金币数量、检查技能冷却、查询玩家位置
diff --git a/GFramework.Core/rule/IBelongToArchitecture.cs b/GFramework.Core/rule/IBelongToArchitecture.cs
index 1c69927..eb98da4 100644
--- a/GFramework.Core/rule/IBelongToArchitecture.cs
+++ b/GFramework.Core/rule/IBelongToArchitecture.cs
@@ -2,16 +2,15 @@ using GFramework.Core.architecture;
namespace GFramework.Core.rule;
-
///
-/// 定义一个接口,用于标识某个对象属于特定的架构体系。
-/// 实现此接口的对象可以通过GetArchitecture方法获取其所属的架构实例。
+/// 定义一个接口,用于标识某个对象属于特定的架构体系。
+/// 实现此接口的对象可以通过GetArchitecture方法获取其所属的架构实例。
///
public interface IBelongToArchitecture
{
///
- /// 获取当前对象所属的架构实例。
+ /// 获取当前对象所属的架构实例。
///
/// 返回实现IArchitecture接口的架构实例
IArchitecture GetArchitecture();
-}
+}
\ No newline at end of file
diff --git a/GFramework.Core/rule/ICanSetArchitecture.cs b/GFramework.Core/rule/ICanSetArchitecture.cs
index 977311c..9fdfd66 100644
--- a/GFramework.Core/rule/ICanSetArchitecture.cs
+++ b/GFramework.Core/rule/ICanSetArchitecture.cs
@@ -3,13 +3,13 @@ using GFramework.Core.architecture;
namespace GFramework.Core.rule;
///
-/// 定义一个接口,用于设置架构实例
+/// 定义一个接口,用于设置架构实例
///
public interface ICanSetArchitecture
{
///
- /// 设置架构实例
+ /// 设置架构实例
///
/// 要设置的架构实例
void SetArchitecture(IArchitecture architecture);
-}
+}
\ No newline at end of file
diff --git a/GFramework.Core/rule/README.md b/GFramework.Core/rule/README.md
index 6704ce0..8da3b87 100644
--- a/GFramework.Core/rule/README.md
+++ b/GFramework.Core/rule/README.md
@@ -11,6 +11,7 @@ Rule 包定义了框架的核心规则接口,这些接口规定了框架各个
标记接口,表示某个对象属于特定的架构体系。
**接口定义:**
+
```csharp
public interface IBelongToArchitecture
{
@@ -19,6 +20,7 @@ public interface IBelongToArchitecture
```
**实现此接口的类型:**
+
- Controller
- System
- Model
@@ -34,6 +36,7 @@ public interface IBelongToArchitecture
定义可以设置架构实例的能力。
**接口定义:**
+
```csharp
public interface ICanSetArchitecture
{
@@ -42,6 +45,7 @@ public interface ICanSetArchitecture
```
**实现此接口的类型:**
+
- Command
- Query
diff --git a/GFramework.Core/system/AbstractSystem.cs b/GFramework.Core/system/AbstractSystem.cs
index bbc68a9..927c34a 100644
--- a/GFramework.Core/system/AbstractSystem.cs
+++ b/GFramework.Core/system/AbstractSystem.cs
@@ -4,32 +4,41 @@ using GFramework.Core.rule;
namespace GFramework.Core.system;
///
-/// 抽象系统基类,实现系统接口的基本功能
-/// 提供架构关联和初始化机制
+/// 抽象系统基类,实现系统接口的基本功能
+/// 提供架构关联和初始化机制
///
public abstract class AbstractSystem : ISystem
{
private IArchitecture _mArchitecture;
///
- /// 获取当前系统所属的架构实例
+ /// 获取当前系统所属的架构实例
///
/// 返回系统关联的架构对象
- IArchitecture IBelongToArchitecture.GetArchitecture() => _mArchitecture;
+ IArchitecture IBelongToArchitecture.GetArchitecture()
+ {
+ return _mArchitecture;
+ }
///
- /// 设置系统所属的架构实例
+ /// 设置系统所属的架构实例
///
/// 要关联的架构对象
- void ICanSetArchitecture.SetArchitecture(IArchitecture architecture) => _mArchitecture = architecture;
+ void ICanSetArchitecture.SetArchitecture(IArchitecture architecture)
+ {
+ _mArchitecture = architecture;
+ }
///
- /// 系统初始化方法,调用抽象初始化方法
+ /// 系统初始化方法,调用抽象初始化方法
///
- void ISystem.Init() => OnInit();
+ void ISystem.Init()
+ {
+ OnInit();
+ }
///
- /// 抽象初始化方法,由子类实现具体的初始化逻辑
+ /// 抽象初始化方法,由子类实现具体的初始化逻辑
///
protected abstract void OnInit();
-}
+}
\ No newline at end of file
diff --git a/GFramework.Core/system/ICanGetSystem.cs b/GFramework.Core/system/ICanGetSystem.cs
index ddbd00e..ecbf630 100644
--- a/GFramework.Core/system/ICanGetSystem.cs
+++ b/GFramework.Core/system/ICanGetSystem.cs
@@ -3,7 +3,7 @@ using GFramework.Core.rule;
namespace GFramework.Core.system;
///
-/// 定义一个接口,表示可以获取系统的对象。
-/// 该接口继承自IBelongToArchitecture接口,用于标识那些属于系统架构并能够获取系统实例的类型。
+/// 定义一个接口,表示可以获取系统的对象。
+/// 该接口继承自IBelongToArchitecture接口,用于标识那些属于系统架构并能够获取系统实例的类型。
///
-public interface ICanGetSystem : IBelongToArchitecture;
+public interface ICanGetSystem : IBelongToArchitecture;
\ No newline at end of file
diff --git a/GFramework.Core/system/ISystem.cs b/GFramework.Core/system/ISystem.cs
index 45a3a3e..4f5bef4 100644
--- a/GFramework.Core/system/ISystem.cs
+++ b/GFramework.Core/system/ISystem.cs
@@ -6,15 +6,15 @@ using GFramework.Core.utility;
namespace GFramework.Core.system;
///
-/// 系统接口,定义了系统的基本行为和功能
-/// 该接口继承了多个框架相关的接口,提供了系统初始化能力
+/// 系统接口,定义了系统的基本行为和功能
+/// 该接口继承了多个框架相关的接口,提供了系统初始化能力
///
public interface ISystem : ICanSetArchitecture, ICanGetModel, ICanGetUtility,
ICanRegisterEvent, ICanSendEvent, ICanGetSystem
{
///
- /// 初始化系统
- /// 在系统被创建后调用,用于执行系统的初始化逻辑
+ /// 初始化系统
+ /// 在系统被创建后调用,用于执行系统的初始化逻辑
///
void Init();
-}
+}
\ No newline at end of file
diff --git a/GFramework.Core/system/README.md b/GFramework.Core/system/README.md
index 9b82309..1cefe54 100644
--- a/GFramework.Core/system/README.md
+++ b/GFramework.Core/system/README.md
@@ -11,6 +11,7 @@ System 包定义了业务逻辑层(Business Logic Layer)。System 负责处
标记接口,表示该类型可以获取其他 System。
**继承关系:**
+
```csharp
public interface ICanGetSystem : IBelongToArchitecture
```
@@ -20,11 +21,13 @@ public interface ICanGetSystem : IBelongToArchitecture
System 接口,定义了系统的基本行为。
**核心成员:**
+
```csharp
void Init(); // 系统初始化方法
```
**继承的能力:**
+
- `ICanSetArchitecture` - 可设置架构
- `ICanGetModel` - 可获取 Model
- `ICanGetUtility` - 可获取 Utility
@@ -39,6 +42,7 @@ void Init(); // 系统初始化方法
抽象 System 基类,提供了 System 的基础实现。
**使用方式:**
+
```csharp
public abstract class AbstractSystem : ISystem
{
@@ -419,11 +423,13 @@ public class GameStateSystem : AbstractSystem
## System vs Model
### Model(数据层)
+
- **职责**:存储数据和状态
- **特点**:被动,等待修改
- **示例**:PlayerModel、InventoryModel
### System(逻辑层)
+
- **职责**:处理业务逻辑,协调 Model
- **特点**:主动,响应事件
- **示例**:CombatSystem、QuestSystem
diff --git a/GFramework.Core/utility/ICanGetUtility.cs b/GFramework.Core/utility/ICanGetUtility.cs
index 2dc1c03..4bb7771 100644
--- a/GFramework.Core/utility/ICanGetUtility.cs
+++ b/GFramework.Core/utility/ICanGetUtility.cs
@@ -3,7 +3,7 @@
namespace GFramework.Core.utility;
///
-/// 定义一个接口,表示可以获取工具类的对象
-/// 该接口继承自IBelongToArchitecture,表明实现此接口的类型属于某个架构组件
+/// 定义一个接口,表示可以获取工具类的对象
+/// 该接口继承自IBelongToArchitecture,表明实现此接口的类型属于某个架构组件
///
-public interface ICanGetUtility : IBelongToArchitecture;
+public interface ICanGetUtility : IBelongToArchitecture;
\ No newline at end of file
diff --git a/GFramework.Core/utility/IUtility.cs b/GFramework.Core/utility/IUtility.cs
index 90366eb..f097af3 100644
--- a/GFramework.Core/utility/IUtility.cs
+++ b/GFramework.Core/utility/IUtility.cs
@@ -1,7 +1,7 @@
namespace GFramework.Core.utility;
///
-/// IUtility接口定义了通用工具类的基本契约
-/// 该接口作为所有工具类实现的基础接口,提供统一的工具方法规范
+/// IUtility接口定义了通用工具类的基本契约
+/// 该接口作为所有工具类实现的基础接口,提供统一的工具方法规范
///
-public interface IUtility;
+public interface IUtility;
\ No newline at end of file
diff --git a/GFramework.Core/utility/README.md b/GFramework.Core/utility/README.md
index 76ed3e9..5446cc6 100644
--- a/GFramework.Core/utility/README.md
+++ b/GFramework.Core/utility/README.md
@@ -2,7 +2,8 @@
## 概述
-Utility 包定义了工具类层。Utility 提供无状态的辅助功能,如数学计算、文件操作、序列化等通用工具方法。与 System 不同,Utility 不依赖架构状态,是纯粹的工具函数集合。
+Utility 包定义了工具类层。Utility 提供无状态的辅助功能,如数学计算、文件操作、序列化等通用工具方法。与 System 不同,Utility
+不依赖架构状态,是纯粹的工具函数集合。
## 核心接口
@@ -11,6 +12,7 @@ Utility 包定义了工具类层。Utility 提供无状态的辅助功能,如
标记接口,表示该类型可以获取 Utility。
**继承关系:**
+
```csharp
public interface ICanGetUtility : IBelongToArchitecture
```
@@ -20,6 +22,7 @@ public interface ICanGetUtility : IBelongToArchitecture
Utility 标记接口,所有工具类都应实现此接口。
**接口定义:**
+
```csharp
public interface IUtility
{
@@ -419,12 +422,14 @@ public class LogUtility : IUtility
## Utility vs System
### Utility(工具层)
+
- **无状态** - 不存储业务数据
- **纯函数** - 相同输入产生相同输出
- **独立性** - 不依赖架构状态
- **可复用** - 可在多个项目中使用
### System(逻辑层)
+
- **有状态** - 可能存储临时状态
- **业务逻辑** - 处理特定业务流程
- **架构依赖** - 需要访问 Model
diff --git a/GFramework.Generator.Attributes/generator/enums/EnumExtensionsAttribute.cs b/GFramework.Generator.Attributes/generator/enums/EnumExtensionsAttribute.cs
index f78769c..b62031d 100644
--- a/GFramework.Generator.Attributes/generator/enums/EnumExtensionsAttribute.cs
+++ b/GFramework.Generator.Attributes/generator/enums/EnumExtensionsAttribute.cs
@@ -1,21 +1,20 @@
-
-using System;
+using System;
namespace GFramework.Generator.Attributes
{
///
- /// 标注在 enum 上,Source Generator 会为该 enum 生成扩展方法。
+ /// 标注在 enum 上,Source Generator 会为该 enum 生成扩展方法。
///
[AttributeUsage(AttributeTargets.Enum)]
public sealed class GenerateEnumExtensionsAttribute : Attribute
{
///
- /// 是否为每个枚举项生成单独的 IsXXX 方法(默认 true)。
+ /// 是否为每个枚举项生成单独的 IsXXX 方法(默认 true)。
///
public bool GenerateIsMethods { get; set; } = true;
///
- /// 是否生成一个 IsIn(params T[]) 方法以简化多值判断(默认 true)。
+ /// 是否生成一个 IsIn(params T[]) 方法以简化多值判断(默认 true)。
///
public bool GenerateIsInMethod { get; set; } = true;
}
diff --git a/GFramework.Generator/GFramework.Generator.csproj b/GFramework.Generator/GFramework.Generator.csproj
index 2223095..593796c 100644
--- a/GFramework.Generator/GFramework.Generator.csproj
+++ b/GFramework.Generator/GFramework.Generator.csproj
@@ -20,7 +20,7 @@
-
+
@@ -33,12 +33,12 @@
-
+
- true
-
+ true
+
diff --git a/GFramework.Generator/README.md b/GFramework.Generator/README.md
index 9aa7518..08b71e1 100644
--- a/GFramework.Generator/README.md
+++ b/GFramework.Generator/README.md
@@ -1,3 +1,4 @@
项目额外的简单代码生成器
目前已有的功能
+
- 为枚举添加两个扩展方法方便判断枚举值
\ No newline at end of file
diff --git a/GFramework.Generator/generator/enums/EnumExtensionsGenerator.cs b/GFramework.Generator/generator/enums/EnumExtensionsGenerator.cs
index 3bc6df3..fdc7ab5 100644
--- a/GFramework.Generator/generator/enums/EnumExtensionsGenerator.cs
+++ b/GFramework.Generator/generator/enums/EnumExtensionsGenerator.cs
@@ -5,121 +5,118 @@ using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
-namespace GFramework.Generator.generator.enums
+namespace GFramework.Generator.generator.enums;
+
+[Generator]
+public class EnumExtensionsGenerator : IIncrementalGenerator
{
- [Generator]
- public class EnumExtensionsGenerator : IIncrementalGenerator
+ private const string AttributeFullName = "GFramework.Generator.Attributes.GenerateEnumExtensionsAttribute";
+
+ public void Initialize(IncrementalGeneratorInitializationContext context)
{
- private const string AttributeFullName = "GFramework.Generator.Attributes.GenerateEnumExtensionsAttribute";
+ // 1. 找到所有 EnumDeclarationSyntax 节点
+ var enumDecls = context.SyntaxProvider
+ .CreateSyntaxProvider(
+ (s, _) => s is EnumDeclarationSyntax,
+ (ctx, _) =>
+ (EnumDecl: (EnumDeclarationSyntax)ctx.Node, ctx.SemanticModel))
+ .Where(t => t.EnumDecl != null);
- public void Initialize(IncrementalGeneratorInitializationContext context)
- {
- // 1. 找到所有 EnumDeclarationSyntax 节点
- var enumDecls = context.SyntaxProvider
- .CreateSyntaxProvider(
- predicate: (s, _) => s is EnumDeclarationSyntax,
- transform: (ctx, _) =>
- (EnumDecl: (EnumDeclarationSyntax)ctx.Node, ctx.SemanticModel))
- .Where(t => t.EnumDecl != null);
-
- // 2. 解析为 symbol 并过滤带 Attribute 的 enum
- var enumSymbols = enumDecls
- .Select((t, _) =>
- {
- var model = t.SemanticModel;
- var enumDecl = t.EnumDecl;
- var symbol = model.GetDeclaredSymbol(enumDecl) as INamedTypeSymbol;
- return symbol;
- })
- .Where(symbol => symbol != null)
- .Select((symbol, _) =>
- {
- // 判断是否包含我们的 Attribute
- var hasAttr = symbol.GetAttributes().Any(ad =>
- ad.AttributeClass?.ToDisplayString() == AttributeFullName ||
- ad.AttributeClass?.ToDisplayString().EndsWith(".GenerateEnumExtensionsAttribute") == true);
- return (Symbol: symbol, HasAttr: hasAttr);
- })
- .Where(x => x.HasAttr)
- .Collect();
-
- // 3. 为每个 enum 生成代码
- context.RegisterSourceOutput(enumSymbols, (spc, list) =>
+ // 2. 解析为 symbol 并过滤带 Attribute 的 enum
+ var enumSymbols = enumDecls
+ .Select((t, _) =>
{
- foreach (var enumSymbol in list.Select(item => item.Symbol))
+ var model = t.SemanticModel;
+ var enumDecl = t.EnumDecl;
+ var symbol = model.GetDeclaredSymbol(enumDecl) as INamedTypeSymbol;
+ return symbol;
+ })
+ .Where(symbol => symbol != null)
+ .Select((symbol, _) =>
+ {
+ // 判断是否包含我们的 Attribute
+ var hasAttr = symbol.GetAttributes().Any(ad =>
+ ad.AttributeClass?.ToDisplayString() == AttributeFullName ||
+ ad.AttributeClass?.ToDisplayString().EndsWith(".GenerateEnumExtensionsAttribute") == true);
+ return (Symbol: symbol, HasAttr: hasAttr);
+ })
+ .Where(x => x.HasAttr)
+ .Collect();
+
+ // 3. 为每个 enum 生成代码
+ context.RegisterSourceOutput(enumSymbols, (spc, list) =>
+ {
+ foreach (var enumSymbol in list.Select(item => item.Symbol))
+ try
{
- try
- {
- var src = GenerateForEnum(enumSymbol);
- var hintName = $"{enumSymbol.Name}.EnumExtensions.g.cs";
- spc.AddSource(hintName, SourceText.From(src, Encoding.UTF8));
- }
- catch (Exception ex)
- {
- // 发生异常时生成一个注释文件(避免完全静默失败)
- var err = $"// EnumExtensionsGenerator failed for {enumSymbol?.Name}: {ex.Message}";
- spc.AddSource($"{enumSymbol?.Name}.EnumExtensions.Error.g.cs",
- SourceText.From(err, Encoding.UTF8));
- }
+ var src = GenerateForEnum(enumSymbol);
+ var hintName = $"{enumSymbol.Name}.EnumExtensions.g.cs";
+ spc.AddSource(hintName, SourceText.From(src, Encoding.UTF8));
}
- });
+ catch (Exception ex)
+ {
+ // 发生异常时生成一个注释文件(避免完全静默失败)
+ var err = $"// EnumExtensionsGenerator failed for {enumSymbol?.Name}: {ex.Message}";
+ spc.AddSource($"{enumSymbol?.Name}.EnumExtensions.Error.g.cs",
+ SourceText.From(err, Encoding.UTF8));
+ }
+ });
+ }
+
+ private static string GenerateForEnum(INamedTypeSymbol enumSymbol)
+ {
+ var ns = enumSymbol.ContainingNamespace.IsGlobalNamespace
+ ? null
+ : enumSymbol.ContainingNamespace.ToDisplayString();
+ var enumName = enumSymbol.Name;
+ var fullEnumName = enumSymbol.ToDisplayString(); // 包含命名空间
+ var members = enumSymbol.GetMembers().OfType().Where(f => f.ConstantValue != null).ToArray();
+
+ var sb = new StringBuilder();
+ sb.AppendLine("// ");
+ sb.AppendLine("using System;");
+ if (!string.IsNullOrEmpty(ns))
+ {
+ sb.AppendLine($"namespace {ns}");
+ sb.AppendLine("{");
+ }
+ else
+ {
+ sb.AppendLine("namespace EnumExtensionsGenerated");
+ sb.AppendLine("{");
}
- private static string GenerateForEnum(INamedTypeSymbol enumSymbol)
- {
- var ns = enumSymbol.ContainingNamespace.IsGlobalNamespace
- ? null
- : enumSymbol.ContainingNamespace.ToDisplayString();
- var enumName = enumSymbol.Name;
- var fullEnumName = enumSymbol.ToDisplayString(); // 包含命名空间
- var members = enumSymbol.GetMembers().OfType().Where(f => f.ConstantValue != null).ToArray();
+ sb.AppendLine($" public static partial class {enumName}Extensions");
+ sb.AppendLine(" {");
- var sb = new StringBuilder();
- sb.AppendLine("// ");
- sb.AppendLine("using System;");
- if (!string.IsNullOrEmpty(ns))
- {
- sb.AppendLine($"namespace {ns}");
- sb.AppendLine("{");
- }
- else
- {
- sb.AppendLine("namespace EnumExtensionsGenerated");
- sb.AppendLine("{");
- }
-
- sb.AppendLine($" public static partial class {enumName}Extensions");
- sb.AppendLine(" {");
-
- // 1. 单项 IsX 方法
+ // 1. 单项 IsX 方法
// 替换原第93行开始的 foreach 块
- var memberChecks = members.Select(m =>
- {
- var memberName = m.Name;
- var safeMethodName = $"Is{memberName}";
- return $@" /// Auto-generated: 是否为 {memberName}
+ var memberChecks = members.Select(m =>
+ {
+ var memberName = m.Name;
+ var safeMethodName = $"Is{memberName}";
+ return $@" /// Auto-generated: 是否为 {memberName}
public static bool {safeMethodName}(this {fullEnumName} value) => value == {fullEnumName}.{memberName};
";
- }).ToArray();
+ }).ToArray();
- sb.Append(string.Join("", memberChecks));
+ sb.Append(string.Join("", memberChecks));
- // 2. IsIn(params ...) 方法
- sb.AppendLine($" /// Auto-generated: 判断是否属于指定集合");
- sb.AppendLine(
- $" public static bool IsIn(this {fullEnumName} value, params {fullEnumName}[] values)");
- sb.AppendLine(" {");
- sb.AppendLine(" if (values == null) return false;");
- sb.AppendLine(" foreach (var v in values) if (value == v) return true;");
- sb.AppendLine(" return false;");
- sb.AppendLine(" }");
+ // 2. IsIn(params ...) 方法
+ sb.AppendLine(" /// Auto-generated: 判断是否属于指定集合");
+ sb.AppendLine(
+ $" public static bool IsIn(this {fullEnumName} value, params {fullEnumName}[] values)");
+ sb.AppendLine(" {");
+ sb.AppendLine(" if (values == null) return false;");
+ sb.AppendLine(" foreach (var v in values) if (value == v) return true;");
+ sb.AppendLine(" return false;");
+ sb.AppendLine(" }");
- sb.AppendLine(" }");
- sb.AppendLine("}"); // namespace
+ sb.AppendLine(" }");
+ sb.AppendLine("}"); // namespace
- return sb.ToString();
- }
+ return sb.ToString();
}
}
\ No newline at end of file
diff --git a/GFramework.csproj b/GFramework.csproj
index 3c6c5ff..478d4d1 100644
--- a/GFramework.csproj
+++ b/GFramework.csproj
@@ -25,37 +25,37 @@
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
- GFramework.Godot\godot\extensions\NodeExtensions.cs
+ GFramework.Godot\godot\extensions\NodeExtensions.cs
- GFramework.Godot\godot\extensions\UnRegisterExtension.cs
+ GFramework.Godot\godot\extensions\UnRegisterExtension.cs
-
-
-
+
+
+
+ ReferenceOutputAssembly="false"/>
diff --git a/README.md b/README.md
index 8774a9b..aa10597 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,9 @@
# 项目介绍
+
本项目参考(CV)自[QFramework](https://github.com/liangxiegame/QFramework)
# 为什么要有这个项目
+
- 原来的项目是单文件框架,我把框架拆成多个文件,方便管理
- 纯粹个人自用,要使用还是请访问[QFramework](https://github.com/liangxiegame/QFramework)
- 至于修改名字,是因为我为了方便会发布GuGet包,假设将来QFramework也要发布GuGet包,那么就会冲突了
\ No newline at end of file