mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-25 13:33:28 +08:00
refactor(core): 重构架构和命令相关代码结构
- 调整了 Architecture 类中字段和方法的布局,提升可读性 - 优化了命令执行逻辑,明确区分有无返回值的命令处理 - 规范了接口和抽象类的注释格式,增强文档清晰度 - 统一了代码风格,对齐缩进与换行符使用 - 补充了事件系统中泛型事件类的功能实现 - 完善了 README 文档中的条目结构和内容表述
This commit is contained in:
parent
6da64eaf01
commit
82713e34f0
@ -9,6 +9,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Godot.SourceGenerators" Version="4.5.1"/>
|
||||||
<PackageReference Include="GodotSharpEditor" Version="4.5.1"/>
|
<PackageReference Include="GodotSharpEditor" Version="4.5.1"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
181
GFramework.Core.Godot/component/DragDropComponent.cs
Normal file
181
GFramework.Core.Godot/component/DragDropComponent.cs
Normal file
@ -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;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 拖拽组件类,用于处理节点的拖放逻辑。
|
||||||
|
/// 实现了 IController 接口以支持架构通信,并通过信号通知拖拽事件的发生。
|
||||||
|
/// </summary>
|
||||||
|
public abstract partial class DragDropComponent : Node, IController
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 当拖拽被取消时触发的信号。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="startingPosition">拖拽起始位置。</param>
|
||||||
|
[Signal]
|
||||||
|
public delegate void DragCanceledEventHandler(Vector2 startingPosition);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当拖拽开始时触发的信号。
|
||||||
|
/// </summary>
|
||||||
|
[Signal]
|
||||||
|
public delegate void DragStartedEventHandler();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当拖拽结束并放置时触发的信号。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="startingPosition">拖拽起始位置。</param>
|
||||||
|
[Signal]
|
||||||
|
public delegate void DroppedEventHandler(Vector2 startingPosition);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 取消注册列表,用于管理需要在节点销毁时取消注册的对象
|
||||||
|
/// </summary>
|
||||||
|
private readonly IUnRegisterList _unRegisterList = new UnRegisterList();
|
||||||
|
|
||||||
|
private bool _isDragging;
|
||||||
|
private Vector2 _offset = Vector2.Zero;
|
||||||
|
|
||||||
|
private Vector2 _startingPosition;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 目标区域,通常是可交互的游戏对象(如单位或物品)所在的碰撞区域。
|
||||||
|
/// </summary>
|
||||||
|
public required Area2D Target { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否启用拖拽功能。若为 false,则忽略所有输入事件。
|
||||||
|
/// </summary>
|
||||||
|
public bool Enable { get; set; }
|
||||||
|
|
||||||
|
public string GroupName { get; set; } = "dragging";
|
||||||
|
|
||||||
|
public int ZIndexMax { get; set; } = 99;
|
||||||
|
public int ZIndexMin { get; set; } = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取游戏架构实例
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>返回游戏架构接口实例</returns>
|
||||||
|
public abstract IArchitecture GetArchitecture();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 节点准备就绪时的回调方法。
|
||||||
|
/// 在节点添加到场景树后调用,绑定目标区域的输入事件处理器。
|
||||||
|
/// </summary>
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
Target = GetParent() as Area2D ?? throw new InvalidOperationException("Target must be an Area2D node.");
|
||||||
|
Target.InputEvent += OnTargetInputEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 处理输入事件的方法
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="event">输入事件对象</param>
|
||||||
|
public override void _Input(InputEvent @event)
|
||||||
|
{
|
||||||
|
// 处理取消拖拽操作:当正在拖拽且按下取消拖拽按键时,执行取消拖拽逻辑
|
||||||
|
if (!_isDragging || Target.IsInvalidNode() || !@event.IsActionPressed("cancel_drag")) return;
|
||||||
|
CancelDragging();
|
||||||
|
// 设置输入为处理,防止输入穿透
|
||||||
|
this.SetInputAsHandled();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 处理目标区域接收到的输入事件。
|
||||||
|
/// 根据当前是否处于拖拽状态以及用户操作决定执行开始、取消或完成拖拽的动作。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="viewport">接收输入事件的视图端口节点。</param>
|
||||||
|
/// <param name="event">发生的输入事件。</param>
|
||||||
|
/// <param name="_">事件索引(未使用)。</param>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 每帧更新逻辑,在拖拽过程中持续更新目标的位置。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="delta">与上一帧的时间间隔(秒)。</param>
|
||||||
|
public override void _Process(double delta)
|
||||||
|
{
|
||||||
|
if (_isDragging && Target.IsValidNode()) Target.GlobalPosition = Target.GetGlobalMousePosition() + _offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 结束拖拽流程的基础方法。
|
||||||
|
/// 清除拖拽标志位并将目标从拖拽组中移除,恢复其层级顺序。
|
||||||
|
/// </summary>
|
||||||
|
private void EndDragging()
|
||||||
|
{
|
||||||
|
_isDragging = false;
|
||||||
|
Target.RemoveFromGroup(GroupName);
|
||||||
|
Target.ZIndex = ZIndexMin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 执行取消拖拽的操作。
|
||||||
|
/// 调用 EndDragging 并发出 DragCanceled 信号。
|
||||||
|
/// </summary>
|
||||||
|
private void CancelDragging()
|
||||||
|
{
|
||||||
|
EndDragging();
|
||||||
|
EmitSignalDragCanceled(_startingPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 开始拖拽操作。
|
||||||
|
/// 设置初始位置和偏移量,将目标加入拖拽组并提升显示层级,最后发出 DragStarted 信号。
|
||||||
|
/// </summary>
|
||||||
|
private void StartDragging()
|
||||||
|
{
|
||||||
|
_isDragging = true;
|
||||||
|
_startingPosition = Target.GlobalPosition;
|
||||||
|
Target.AddToGroup(GroupName);
|
||||||
|
Target.ZIndex = ZIndexMax;
|
||||||
|
_offset = Target.GlobalPosition - Target.GetGlobalMousePosition();
|
||||||
|
EmitSignalDragStarted();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 完成一次拖拽操作。
|
||||||
|
/// 调用 EndDragging 方法并发出 Dropped 信号。
|
||||||
|
/// </summary>
|
||||||
|
private void Drop()
|
||||||
|
{
|
||||||
|
EndDragging();
|
||||||
|
EmitSignalDropped(_startingPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 节点退出场景树时的回调方法。
|
||||||
|
/// 在节点从场景树移除前调用,用于清理资源。
|
||||||
|
/// </summary>
|
||||||
|
public override void _ExitTree()
|
||||||
|
{
|
||||||
|
_unRegisterList.UnRegisterAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,4 @@
|
|||||||
using System;
|
using Godot;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Godot;
|
|
||||||
|
|
||||||
namespace GFramework.Core.Godot.extensions;
|
namespace GFramework.Core.Godot.extensions;
|
||||||
|
|
||||||
@ -16,22 +14,13 @@ public static class NodeExtensions
|
|||||||
public static void QueueFreeX(this Node? node)
|
public static void QueueFreeX(this Node? node)
|
||||||
{
|
{
|
||||||
// 检查节点是否为空
|
// 检查节点是否为空
|
||||||
if (node is null)
|
if (node is null) return;
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查节点实例是否有效
|
// 检查节点实例是否有效
|
||||||
if (!GodotObject.IsInstanceValid(node))
|
if (!GodotObject.IsInstanceValid(node)) return;
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查节点是否已经加入删除队列
|
// 检查节点是否已经加入删除队列
|
||||||
if (node.IsQueuedForDeletion())
|
if (node.IsQueuedForDeletion()) return;
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 延迟调用QueueFree方法,避免在当前帧中直接删除节点
|
// 延迟调用QueueFree方法,避免在当前帧中直接删除节点
|
||||||
node.CallDeferred(Node.MethodName.QueueFree);
|
node.CallDeferred(Node.MethodName.QueueFree);
|
||||||
@ -44,22 +33,13 @@ public static class NodeExtensions
|
|||||||
public static void FreeX(this Node? node)
|
public static void FreeX(this Node? node)
|
||||||
{
|
{
|
||||||
// 检查节点是否为空
|
// 检查节点是否为空
|
||||||
if (node is null)
|
if (node is null) return;
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查节点实例是否有效
|
// 检查节点实例是否有效
|
||||||
if (!GodotObject.IsInstanceValid(node))
|
if (!GodotObject.IsInstanceValid(node)) return;
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查节点是否已经加入删除队列
|
// 检查节点是否已经加入删除队列
|
||||||
if (node.IsQueuedForDeletion())
|
if (node.IsQueuedForDeletion()) return;
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 立即释放节点资源
|
// 立即释放节点资源
|
||||||
node.Free();
|
node.Free();
|
||||||
@ -71,10 +51,7 @@ public static class NodeExtensions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static async Task WaitUntilReady(this Node node)
|
public static async Task WaitUntilReady(this Node node)
|
||||||
{
|
{
|
||||||
if (!node.IsInsideTree())
|
if (!node.IsInsideTree()) await node.ToSignal(node, Node.SignalName.Ready);
|
||||||
{
|
|
||||||
await node.ToSignal(node, Node.SignalName.Ready);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -95,7 +72,6 @@ public static class NodeExtensions
|
|||||||
/// 1. 为 null,或者
|
/// 1. 为 null,或者
|
||||||
/// 2. Godot 实例已被释放,或者
|
/// 2. Godot 实例已被释放,或者
|
||||||
/// 3. 尚未加入 SceneTree
|
/// 3. 尚未加入 SceneTree
|
||||||
///
|
|
||||||
/// 返回 true 表示该节点不可用。
|
/// 返回 true 表示该节点不可用。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool IsInvalidNode(this Node? node)
|
public static bool IsInvalidNode(this Node? node)
|
||||||
@ -137,7 +113,7 @@ public static class NodeExtensions
|
|||||||
public static T? FindChildX<T>(this Node node, string name, bool recursive = true)
|
public static T? FindChildX<T>(this Node node, string name, bool recursive = true)
|
||||||
where T : Node
|
where T : Node
|
||||||
{
|
{
|
||||||
var child = node.FindChild(name, recursive, owned: false);
|
var child = node.FindChild(name, recursive, false);
|
||||||
return child as T;
|
return child as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,6 +160,7 @@ public static class NodeExtensions
|
|||||||
{
|
{
|
||||||
return node.GetParent() as T;
|
return node.GetParent() as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取场景树的根节点的第一个子节点
|
/// 获取场景树的根节点的第一个子节点
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -263,6 +240,4 @@ public static class NodeExtensions
|
|||||||
if (node != null && GodotObject.IsInstanceValid(node))
|
if (node != null && GodotObject.IsInstanceValid(node))
|
||||||
node.CallDeferred(method);
|
node.CallDeferred(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -102,6 +102,7 @@ Event ──┘
|
|||||||
### 为什么需要这个框架?
|
### 为什么需要这个框架?
|
||||||
|
|
||||||
在传统的 Godot 开发中,我们经常遇到这些问题:
|
在传统的 Godot 开发中,我们经常遇到这些问题:
|
||||||
|
|
||||||
- 💔 **代码耦合严重**:UI 直接访问游戏逻辑,逻辑直接操作 UI
|
- 💔 **代码耦合严重**:UI 直接访问游戏逻辑,逻辑直接操作 UI
|
||||||
- 🔄 **难以维护**:修改一个功能需要改动多个文件
|
- 🔄 **难以维护**:修改一个功能需要改动多个文件
|
||||||
- 🐛 **难以测试**:业务逻辑和 UI 混在一起无法独立测试
|
- 🐛 **难以测试**:业务逻辑和 UI 混在一起无法独立测试
|
||||||
@ -133,6 +134,7 @@ public class GameArchitecture : Architecture<GameArchitecture>
|
|||||||
```
|
```
|
||||||
|
|
||||||
**优势**:
|
**优势**:
|
||||||
|
|
||||||
- ✅ **单例模式**:通过 `GameArchitecture.Interface` 全局访问
|
- ✅ **单例模式**:通过 `GameArchitecture.Interface` 全局访问
|
||||||
- ✅ **自动初始化**:注册时自动调用组件的 Init 方法
|
- ✅ **自动初始化**:注册时自动调用组件的 Init 方法
|
||||||
- ✅ **依赖注入**:组件自动获得架构引用,无需手动传递
|
- ✅ **依赖注入**:组件自动获得架构引用,无需手动传递
|
||||||
@ -173,12 +175,14 @@ public class PlayerModel : AbstractModel
|
|||||||
```
|
```
|
||||||
|
|
||||||
**优势**:
|
**优势**:
|
||||||
|
|
||||||
- ✅ **数据响应式**:BindableProperty 让数据变化自动通知 UI
|
- ✅ **数据响应式**:BindableProperty 让数据变化自动通知 UI
|
||||||
- ✅ **职责单一**:只存储数据,不包含复杂业务逻辑
|
- ✅ **职责单一**:只存储数据,不包含复杂业务逻辑
|
||||||
- ✅ **易于测试**:可以独立测试数据逻辑
|
- ✅ **易于测试**:可以独立测试数据逻辑
|
||||||
- ✅ **数据持久化**:可以轻松序列化整个 Model 进行存档
|
- ✅ **数据持久化**:可以轻松序列化整个 Model 进行存档
|
||||||
|
|
||||||
**为什么不在 Model 中写业务逻辑?**
|
**为什么不在 Model 中写业务逻辑?**
|
||||||
|
|
||||||
- 保持 Model 简单纯粹,业务逻辑应该在 System 中处理
|
- 保持 Model 简单纯粹,业务逻辑应该在 System 中处理
|
||||||
- Model 应该是"被动"的,等待其他组件修改它
|
- Model 应该是"被动"的,等待其他组件修改它
|
||||||
|
|
||||||
@ -209,12 +213,14 @@ public class CombatSystem : AbstractSystem
|
|||||||
```
|
```
|
||||||
|
|
||||||
**优势**:
|
**优势**:
|
||||||
|
|
||||||
- ✅ **事件驱动**:通过事件解耦,不同 System 之间松耦合
|
- ✅ **事件驱动**:通过事件解耦,不同 System 之间松耦合
|
||||||
- ✅ **可组合**:多个 System 协同工作,每个专注自己的领域
|
- ✅ **可组合**:多个 System 协同工作,每个专注自己的领域
|
||||||
- ✅ **易于扩展**:新增功能只需添加新的 System 和事件监听
|
- ✅ **易于扩展**:新增功能只需添加新的 System 和事件监听
|
||||||
- ✅ **独立测试**:可以模拟事件来测试 System 的逻辑
|
- ✅ **独立测试**:可以模拟事件来测试 System 的逻辑
|
||||||
|
|
||||||
**System 与 Model 的关系**:
|
**System 与 Model 的关系**:
|
||||||
|
|
||||||
- System 读取和修改 Model 的数据
|
- System 读取和修改 Model 的数据
|
||||||
- System 不应该存储重要的游戏状态(状态应在 Model 中)
|
- System 不应该存储重要的游戏状态(状态应在 Model 中)
|
||||||
- System 可以存储临时的计算结果或缓存
|
- System 可以存储临时的计算结果或缓存
|
||||||
@ -251,18 +257,21 @@ public partial class PlayerController : Node, IController
|
|||||||
```
|
```
|
||||||
|
|
||||||
**优势**:
|
**优势**:
|
||||||
|
|
||||||
- ✅ **自动更新 UI**:通过 BindableProperty,数据变化自动反映到界面
|
- ✅ **自动更新 UI**:通过 BindableProperty,数据变化自动反映到界面
|
||||||
- ✅ **生命周期管理**:自动注销监听,避免内存泄漏
|
- ✅ **生命周期管理**:自动注销监听,避免内存泄漏
|
||||||
- ✅ **分离关注点**:UI 逻辑和业务逻辑完全分离
|
- ✅ **分离关注点**:UI 逻辑和业务逻辑完全分离
|
||||||
- ✅ **易于修改 UI**:改变 UI 不影响业务逻辑
|
- ✅ **易于修改 UI**:改变 UI 不影响业务逻辑
|
||||||
|
|
||||||
**为什么使用 RegisterWithInitValue?**
|
**为什么使用 RegisterWithInitValue?**
|
||||||
|
|
||||||
- 注册监听时立即获得当前值,避免 UI 显示空白
|
- 注册监听时立即获得当前值,避免 UI 显示空白
|
||||||
- 后续数据变化会自动触发更新
|
- 后续数据变化会自动触发更新
|
||||||
|
|
||||||
### 完成!现在你有了一个完整的架构
|
### 完成!现在你有了一个完整的架构
|
||||||
|
|
||||||
这 4 步完成后,你就拥有了:
|
这 4 步完成后,你就拥有了:
|
||||||
|
|
||||||
- 📦 **清晰的数据层**(Model)
|
- 📦 **清晰的数据层**(Model)
|
||||||
- 🧠 **独立的业务逻辑**(System)
|
- 🧠 **独立的业务逻辑**(System)
|
||||||
- 🎮 **灵活的控制层**(Controller)
|
- 🎮 **灵活的控制层**(Controller)
|
||||||
@ -278,7 +287,7 @@ public partial class PlayerController : Node, IController
|
|||||||
## 包说明
|
## 包说明
|
||||||
|
|
||||||
| 包名 | 职责 | 文档 |
|
| 包名 | 职责 | 文档 |
|
||||||
|-----|------|------|
|
|------------------|-----------------|---------------------------------|
|
||||||
| **architecture** | 架构核心,管理所有组件生命周期 | [📖 查看](architecture/README.md) |
|
| **architecture** | 架构核心,管理所有组件生命周期 | [📖 查看](architecture/README.md) |
|
||||||
| **model** | 数据模型层,存储游戏状态 | [📖 查看](model/README.md) |
|
| **model** | 数据模型层,存储游戏状态 | [📖 查看](model/README.md) |
|
||||||
| **system** | 业务逻辑层,处理游戏系统 | [📖 查看](system/README.md) |
|
| **system** | 业务逻辑层,处理游戏系统 | [📖 查看](system/README.md) |
|
||||||
@ -346,6 +355,7 @@ Controller: Health.RegisterWithInitValue(hp => UpdateUI(hp))
|
|||||||
#### ✅ 好的实践 vs ❌ 坏的实践
|
#### ✅ 好的实践 vs ❌ 坏的实践
|
||||||
|
|
||||||
**Model 层**:
|
**Model 层**:
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// ✅ 好:只存储数据
|
// ✅ 好:只存储数据
|
||||||
public class PlayerModel : AbstractModel
|
public class PlayerModel : AbstractModel
|
||||||
@ -367,6 +377,7 @@ public class PlayerModel : AbstractModel
|
|||||||
```
|
```
|
||||||
|
|
||||||
**System 层**:
|
**System 层**:
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// ✅ 好:处理业务逻辑
|
// ✅ 好:处理业务逻辑
|
||||||
public class CombatSystem : AbstractSystem
|
public class CombatSystem : AbstractSystem
|
||||||
@ -398,6 +409,7 @@ public class CombatSystem : AbstractSystem
|
|||||||
```
|
```
|
||||||
|
|
||||||
**Controller 层**:
|
**Controller 层**:
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// ✅ 好:只处理 UI 和用户输入
|
// ✅ 好:只处理 UI 和用户输入
|
||||||
public partial class AttackButton : Button, IController
|
public partial class AttackButton : Button, IController
|
||||||
@ -431,7 +443,7 @@ public partial class AttackButton : Button, IController
|
|||||||
不同的通信方式适用于不同场景,选对方式能让代码更优雅。
|
不同的通信方式适用于不同场景,选对方式能让代码更优雅。
|
||||||
|
|
||||||
| 通信方式 | 使用场景 | 示例 | 优势 |
|
| 通信方式 | 使用场景 | 示例 | 优势 |
|
||||||
|---------|---------|------|------|
|
|----------------------|------------|----------------|----------|
|
||||||
| **Command** | 用户操作、修改状态 | 购买物品、攻击敌人 | 可撤销、可记录 |
|
| **Command** | 用户操作、修改状态 | 购买物品、攻击敌人 | 可撤销、可记录 |
|
||||||
| **Query** | 查询数据、检查条件 | 查询金币数量、检查是否可购买 | 明确只读意图 |
|
| **Query** | 查询数据、检查条件 | 查询金币数量、检查是否可购买 | 明确只读意图 |
|
||||||
| **Event** | 通知其他组件 | 玩家死亡、物品拾取 | 松耦合、可扩展 |
|
| **Event** | 通知其他组件 | 玩家死亡、物品拾取 | 松耦合、可扩展 |
|
||||||
@ -527,6 +539,7 @@ public partial class GoldDisplay : Label, IController
|
|||||||
**为什么需要注销?**
|
**为什么需要注销?**
|
||||||
|
|
||||||
忘记注销监听器会导致:
|
忘记注销监听器会导致:
|
||||||
|
|
||||||
- 💥 **内存泄漏**:对象无法被 GC 回收
|
- 💥 **内存泄漏**:对象无法被 GC 回收
|
||||||
- 🐛 **逻辑错误**:已销毁的对象仍在响应事件
|
- 🐛 **逻辑错误**:已销毁的对象仍在响应事件
|
||||||
- 📉 **性能下降**:无用的监听器消耗资源
|
- 📉 **性能下降**:无用的监听器消耗资源
|
||||||
@ -726,6 +739,7 @@ public class CombatSystemTests
|
|||||||
```
|
```
|
||||||
|
|
||||||
**优势**:
|
**优势**:
|
||||||
|
|
||||||
- 不需要启动游戏就能测试逻辑
|
- 不需要启动游戏就能测试逻辑
|
||||||
- 可以快速验证各种边界情况
|
- 可以快速验证各种边界情况
|
||||||
- 易于进行回归测试
|
- 易于进行回归测试
|
||||||
@ -840,6 +854,7 @@ protected override void Init()
|
|||||||
```
|
```
|
||||||
|
|
||||||
**优势总结**:
|
**优势总结**:
|
||||||
|
|
||||||
- 数据驱动,易于存档
|
- 数据驱动,易于存档
|
||||||
- 事件解耦,易于扩展
|
- 事件解耦,易于扩展
|
||||||
- UI 自动化,不会遗漏更新
|
- UI 自动化,不会遗漏更新
|
||||||
@ -854,12 +869,14 @@ protected override void Init()
|
|||||||
**理念**:每个类只负责一件事,只有一个改变的理由。
|
**理念**:每个类只负责一件事,只有一个改变的理由。
|
||||||
|
|
||||||
**在框架中的体现**:
|
**在框架中的体现**:
|
||||||
|
|
||||||
- **Model**:只负责存储数据
|
- **Model**:只负责存储数据
|
||||||
- **System**:只负责处理业务逻辑
|
- **System**:只负责处理业务逻辑
|
||||||
- **Controller**:只负责 UI 交互
|
- **Controller**:只负责 UI 交互
|
||||||
- **Utility**:只负责提供工具方法
|
- **Utility**:只负责提供工具方法
|
||||||
|
|
||||||
**好处**:
|
**好处**:
|
||||||
|
|
||||||
- 代码更容易理解和维护
|
- 代码更容易理解和维护
|
||||||
- 修改一个功能不会影响其他功能
|
- 修改一个功能不会影响其他功能
|
||||||
- 单元测试更简单
|
- 单元测试更简单
|
||||||
@ -869,11 +886,13 @@ protected override void Init()
|
|||||||
**理念**:对扩展开放,对修改封闭。
|
**理念**:对扩展开放,对修改封闭。
|
||||||
|
|
||||||
**在框架中的实现**:
|
**在框架中的实现**:
|
||||||
|
|
||||||
- 通过**事件系统**添加新功能,无需修改现有代码
|
- 通过**事件系统**添加新功能,无需修改现有代码
|
||||||
- 新的 System 可以监听现有事件,插入自己的逻辑
|
- 新的 System 可以监听现有事件,插入自己的逻辑
|
||||||
- 符合"插件式"的架构设计
|
- 符合"插件式"的架构设计
|
||||||
|
|
||||||
**示例**:
|
**示例**:
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// 现有:战斗系统
|
// 现有:战斗系统
|
||||||
public class CombatSystem : AbstractSystem
|
public class CombatSystem : AbstractSystem
|
||||||
@ -908,11 +927,13 @@ public class CriticalSystem : AbstractSystem
|
|||||||
**理念**:依赖抽象(接口)而非具体实现。
|
**理念**:依赖抽象(接口)而非具体实现。
|
||||||
|
|
||||||
**在框架中的应用**:
|
**在框架中的应用**:
|
||||||
|
|
||||||
- 所有组件通过接口交互
|
- 所有组件通过接口交互
|
||||||
- 通过 IoC 容器注入依赖
|
- 通过 IoC 容器注入依赖
|
||||||
- 易于替换实现和编写测试
|
- 易于替换实现和编写测试
|
||||||
|
|
||||||
**好处**:
|
**好处**:
|
||||||
|
|
||||||
- 降低耦合度
|
- 降低耦合度
|
||||||
- 易于进行单元测试(可以 mock)
|
- 易于进行单元测试(可以 mock)
|
||||||
- 可以灵活替换实现
|
- 可以灵活替换实现
|
||||||
@ -922,6 +943,7 @@ public class CriticalSystem : AbstractSystem
|
|||||||
**理念**:使用多个专门的接口,而不是一个庞大的接口。
|
**理念**:使用多个专门的接口,而不是一个庞大的接口。
|
||||||
|
|
||||||
**在框架中的体现**:
|
**在框架中的体现**:
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// 小而专注的接口
|
// 小而专注的接口
|
||||||
public interface ICanGetModel : IBelongToArchitecture { }
|
public interface ICanGetModel : IBelongToArchitecture { }
|
||||||
@ -936,6 +958,7 @@ public interface IController :
|
|||||||
```
|
```
|
||||||
|
|
||||||
**优势**:
|
**优势**:
|
||||||
|
|
||||||
- 类只需要实现它真正需要的方法
|
- 类只需要实现它真正需要的方法
|
||||||
- 接口更容易理解和使用
|
- 接口更容易理解和使用
|
||||||
- 减少不必要的依赖
|
- 减少不必要的依赖
|
||||||
@ -945,11 +968,13 @@ public interface IController :
|
|||||||
**理念**:通过接口组合获得能力,而不是通过继承。
|
**理念**:通过接口组合获得能力,而不是通过继承。
|
||||||
|
|
||||||
**传统继承的问题**:
|
**传统继承的问题**:
|
||||||
|
|
||||||
- 继承层次深,难以理解
|
- 继承层次深,难以理解
|
||||||
- 子类与父类紧密耦合
|
- 子类与父类紧密耦合
|
||||||
- 难以灵活组合能力
|
- 难以灵活组合能力
|
||||||
|
|
||||||
**框架的解决方案**:
|
**框架的解决方案**:
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// ✅ 通过接口组合能力
|
// ✅ 通过接口组合能力
|
||||||
public interface IController :
|
public interface IController :
|
||||||
@ -967,7 +992,7 @@ public class BattleController : GameController { }
|
|||||||
### 框架核心设计模式 🎨
|
### 框架核心设计模式 🎨
|
||||||
|
|
||||||
| 设计模式 | 应用位置 | 解决的问题 | 带来的好处 |
|
| 设计模式 | 应用位置 | 解决的问题 | 带来的好处 |
|
||||||
|---------|---------|-----------|-----------|
|
|-----------|--------------|-----------|---------|
|
||||||
| **单例模式** | Architecture | 全局唯一的架构实例 | 统一的组件管理 |
|
| **单例模式** | Architecture | 全局唯一的架构实例 | 统一的组件管理 |
|
||||||
| **工厂模式** | IoC 容器 | 组件的创建和管理 | 解耦创建逻辑 |
|
| **工厂模式** | IoC 容器 | 组件的创建和管理 | 解耦创建逻辑 |
|
||||||
| **观察者模式** | Event 系统 | 组件间的通信 | 松耦合通信 |
|
| **观察者模式** | Event 系统 | 组件间的通信 | 松耦合通信 |
|
||||||
@ -979,26 +1004,31 @@ public class BattleController : GameController { }
|
|||||||
### 为什么这样设计?🤔
|
### 为什么这样设计?🤔
|
||||||
|
|
||||||
#### 1. 降低学习成本
|
#### 1. 降低学习成本
|
||||||
|
|
||||||
- 遵循业界标准模式和原则
|
- 遵循业界标准模式和原则
|
||||||
- 有经验的开发者能快速上手
|
- 有经验的开发者能快速上手
|
||||||
- 清晰的分层易于理解
|
- 清晰的分层易于理解
|
||||||
|
|
||||||
#### 2. 提高代码质量
|
#### 2. 提高代码质量
|
||||||
|
|
||||||
- 强制分层,避免意大利面代码
|
- 强制分层,避免意大利面代码
|
||||||
- 职责明确,减少 bug
|
- 职责明确,减少 bug
|
||||||
- 易于 Code Review
|
- 易于 Code Review
|
||||||
|
|
||||||
#### 3. 便于团队协作
|
#### 3. 便于团队协作
|
||||||
|
|
||||||
- 清晰的职责划分,减少冲突
|
- 清晰的职责划分,减少冲突
|
||||||
- 统一的代码风格
|
- 统一的代码风格
|
||||||
- 新人容易融入项目
|
- 新人容易融入项目
|
||||||
|
|
||||||
#### 4. 易于维护扩展
|
#### 4. 易于维护扩展
|
||||||
|
|
||||||
- 符合 SOLID 原则
|
- 符合 SOLID 原则
|
||||||
- 通过事件添加功能无需修改现有代码
|
- 通过事件添加功能无需修改现有代码
|
||||||
- 模块化设计,易于替换
|
- 模块化设计,易于替换
|
||||||
|
|
||||||
#### 5. 支持单元测试
|
#### 5. 支持单元测试
|
||||||
|
|
||||||
- 依赖注入让 mock 变得简单
|
- 依赖注入让 mock 变得简单
|
||||||
- 接口设计便于测试
|
- 接口设计便于测试
|
||||||
- 业务逻辑与 UI 分离,可独立测试
|
- 业务逻辑与 UI 分离,可独立测试
|
||||||
@ -1006,16 +1036,19 @@ public class BattleController : GameController { }
|
|||||||
### 架构演进建议 🚀
|
### 架构演进建议 🚀
|
||||||
|
|
||||||
#### 小型项目(< 5000 行代码)
|
#### 小型项目(< 5000 行代码)
|
||||||
|
|
||||||
- 使用基础的 MVC 分层
|
- 使用基础的 MVC 分层
|
||||||
- 适度使用 Command 和 Query
|
- 适度使用 Command 和 Query
|
||||||
- 事件系统用于关键通知
|
- 事件系统用于关键通知
|
||||||
|
|
||||||
#### 中型项目(5000-20000 行)
|
#### 中型项目(5000-20000 行)
|
||||||
|
|
||||||
- 完整使用框架所有特性
|
- 完整使用框架所有特性
|
||||||
- 细分 System 的职责
|
- 细分 System 的职责
|
||||||
- 引入更多 Utility 复用代码
|
- 引入更多 Utility 复用代码
|
||||||
|
|
||||||
#### 大型项目(> 20000 行)
|
#### 大型项目(> 20000 行)
|
||||||
|
|
||||||
- 考虑按功能模块拆分多个 Architecture
|
- 考虑按功能模块拆分多个 Architecture
|
||||||
- 使用事件总线连接不同模块
|
- 使用事件总线连接不同模块
|
||||||
- 引入领域驱动设计(DDD)概念
|
- 引入领域驱动设计(DDD)概念
|
||||||
@ -1023,6 +1056,7 @@ public class BattleController : GameController { }
|
|||||||
### 常见反模式 ⚠️
|
### 常见反模式 ⚠️
|
||||||
|
|
||||||
#### 反模式 1:上帝类(God Class)
|
#### 反模式 1:上帝类(God Class)
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// ❌ 一个类做所有事情
|
// ❌ 一个类做所有事情
|
||||||
public class GameManager
|
public class GameManager
|
||||||
@ -1042,6 +1076,7 @@ public class SaveSystem { /* 只负责存档 */ }
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### 反模式 2:循环依赖
|
#### 反模式 2:循环依赖
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// ❌ A 依赖 B,B 又依赖 A
|
// ❌ A 依赖 B,B 又依赖 A
|
||||||
public class SystemA
|
public class SystemA
|
||||||
@ -1071,6 +1106,7 @@ public class SystemB
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### 反模式 3:过度设计
|
#### 反模式 3:过度设计
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// ❌ 简单功能过度抽象
|
// ❌ 简单功能过度抽象
|
||||||
public interface IClickable { }
|
public interface IClickable { }
|
||||||
|
|||||||
@ -15,26 +15,6 @@ namespace GFramework.Core.architecture;
|
|||||||
/// <typeparam name="T">派生类类型,用于实现单例</typeparam>
|
/// <typeparam name="T">派生类类型,用于实现单例</typeparam>
|
||||||
public abstract class Architecture<T> : IArchitecture where T : Architecture<T>, new()
|
public abstract class Architecture<T> : IArchitecture where T : Architecture<T>, new()
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// 标记架构是否已初始化完成
|
|
||||||
/// </summary>
|
|
||||||
private bool _mInited;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 存储尚未初始化的系统集合,在初始化阶段统一调用Init方法
|
|
||||||
/// </summary>
|
|
||||||
private readonly HashSet<ISystem> _mSystems = [];
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 存储尚未初始化的模型集合,在初始化阶段统一调用Init方法
|
|
||||||
/// </summary>
|
|
||||||
private readonly HashSet<IModel> _mModels = [];
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 注册补丁委托,允许在架构创建后执行额外逻辑
|
|
||||||
/// </summary>
|
|
||||||
public static Action<T> OnRegisterPatch { get; set; } = _ => { };
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 静态只读字段,用于延迟初始化架构实例
|
/// 静态只读字段,用于延迟初始化架构实例
|
||||||
/// 使用Lazy确保线程安全的单例模式实现
|
/// 使用Lazy确保线程安全的单例模式实现
|
||||||
@ -58,18 +38,12 @@ public abstract class Architecture<T> : IArchitecture where T : Architecture<T>,
|
|||||||
OnRegisterPatch?.Invoke(arch);
|
OnRegisterPatch?.Invoke(arch);
|
||||||
|
|
||||||
// 初始化所有已注册但尚未初始化的模型
|
// 初始化所有已注册但尚未初始化的模型
|
||||||
foreach (var model in arch._mModels)
|
foreach (var model in arch._mModels) model.Init();
|
||||||
{
|
|
||||||
model.Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
arch._mModels.Clear();
|
arch._mModels.Clear();
|
||||||
|
|
||||||
// 初始化所有已注册但尚未初始化的系统
|
// 初始化所有已注册但尚未初始化的系统
|
||||||
foreach (var system in arch._mSystems)
|
foreach (var system in arch._mSystems) system.Init();
|
||||||
{
|
|
||||||
system.Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
arch._mSystems.Clear();
|
arch._mSystems.Clear();
|
||||||
|
|
||||||
@ -77,6 +51,36 @@ public abstract class Architecture<T> : IArchitecture where T : Architecture<T>,
|
|||||||
return arch;
|
return arch;
|
||||||
}, LazyThreadSafetyMode.ExecutionAndPublication);
|
}, LazyThreadSafetyMode.ExecutionAndPublication);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 控制反转容器,用于存储和获取各种服务(如系统、模型、工具)
|
||||||
|
/// </summary>
|
||||||
|
private readonly IocContainer _mContainer = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 存储尚未初始化的模型集合,在初始化阶段统一调用Init方法
|
||||||
|
/// </summary>
|
||||||
|
private readonly HashSet<IModel> _mModels = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 存储尚未初始化的系统集合,在初始化阶段统一调用Init方法
|
||||||
|
/// </summary>
|
||||||
|
private readonly HashSet<ISystem> _mSystems = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 类型化事件系统,负责事件的发布与订阅管理
|
||||||
|
/// </summary>
|
||||||
|
private readonly TypeEventSystem _mTypeEventSystem = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 标记架构是否已初始化完成
|
||||||
|
/// </summary>
|
||||||
|
private bool _mInited;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 注册补丁委托,允许在架构创建后执行额外逻辑
|
||||||
|
/// </summary>
|
||||||
|
public static Action<T> OnRegisterPatch { get; set; } = _ => { };
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取架构实例的受保护静态属性
|
/// 获取架构实例的受保护静态属性
|
||||||
/// 通过Lazy初始化确保只创建一个实例
|
/// 通过Lazy初始化确保只创建一个实例
|
||||||
@ -91,17 +95,6 @@ public abstract class Architecture<T> : IArchitecture where T : Architecture<T>,
|
|||||||
/// <returns>IArchitecture接口类型的架构实例</returns>
|
/// <returns>IArchitecture接口类型的架构实例</returns>
|
||||||
public static IArchitecture Interface => MArchitectureLazy.Value;
|
public static IArchitecture Interface => MArchitectureLazy.Value;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 抽象初始化方法,由子类重写以进行自定义初始化操作
|
|
||||||
/// </summary>
|
|
||||||
protected abstract void Init();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 控制反转容器,用于存储和获取各种服务(如系统、模型、工具)
|
|
||||||
/// </summary>
|
|
||||||
private readonly IocContainer _mContainer = new();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 注册一个系统到架构中。
|
/// 注册一个系统到架构中。
|
||||||
/// 若当前未初始化,则暂存至待初始化列表;否则立即初始化该系统。
|
/// 若当前未初始化,则暂存至待初始化列表;否则立即初始化该系统。
|
||||||
@ -114,14 +107,10 @@ public abstract class Architecture<T> : IArchitecture where T : Architecture<T>,
|
|||||||
_mContainer.Register(system);
|
_mContainer.Register(system);
|
||||||
|
|
||||||
if (!_mInited)
|
if (!_mInited)
|
||||||
{
|
|
||||||
_mSystems.Add(system);
|
_mSystems.Add(system);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
system.Init();
|
system.Init();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 注册一个模型到架构中。
|
/// 注册一个模型到架构中。
|
||||||
@ -135,14 +124,10 @@ public abstract class Architecture<T> : IArchitecture where T : Architecture<T>,
|
|||||||
_mContainer.Register(model);
|
_mContainer.Register(model);
|
||||||
|
|
||||||
if (!_mInited)
|
if (!_mInited)
|
||||||
{
|
|
||||||
_mModels.Add(model);
|
_mModels.Add(model);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
model.Init();
|
model.Init();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 注册一个工具到架构中。
|
/// 注册一个工具到架构中。
|
||||||
@ -150,29 +135,40 @@ public abstract class Architecture<T> : IArchitecture where T : Architecture<T>,
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TUtility">要注册的工具类型</typeparam>
|
/// <typeparam name="TUtility">要注册的工具类型</typeparam>
|
||||||
/// <param name="utility">要注册的工具实例</param>
|
/// <param name="utility">要注册的工具实例</param>
|
||||||
public void RegisterUtility<TUtility>(TUtility utility) where TUtility : IUtility =>
|
public void RegisterUtility<TUtility>(TUtility utility) where TUtility : IUtility
|
||||||
|
{
|
||||||
_mContainer.Register(utility);
|
_mContainer.Register(utility);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 从IOC容器中获取指定类型的系统实例
|
/// 从IOC容器中获取指定类型的系统实例
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TSystem">目标系统类型</typeparam>
|
/// <typeparam name="TSystem">目标系统类型</typeparam>
|
||||||
/// <returns>对应的系统实例</returns>
|
/// <returns>对应的系统实例</returns>
|
||||||
public TSystem GetSystem<TSystem>() where TSystem : class, ISystem => _mContainer.Get<TSystem>();
|
public TSystem GetSystem<TSystem>() where TSystem : class, ISystem
|
||||||
|
{
|
||||||
|
return _mContainer.Get<TSystem>();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 从IOC容器中获取指定类型的模型实例
|
/// 从IOC容器中获取指定类型的模型实例
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TModel">目标模型类型</typeparam>
|
/// <typeparam name="TModel">目标模型类型</typeparam>
|
||||||
/// <returns>对应的模型实例</returns>
|
/// <returns>对应的模型实例</returns>
|
||||||
public TModel GetModel<TModel>() where TModel : class, IModel => _mContainer.Get<TModel>();
|
public TModel GetModel<TModel>() where TModel : class, IModel
|
||||||
|
{
|
||||||
|
return _mContainer.Get<TModel>();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 从IOC容器中获取指定类型的工具实例
|
/// 从IOC容器中获取指定类型的工具实例
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TUtility">目标工具类型</typeparam>
|
/// <typeparam name="TUtility">目标工具类型</typeparam>
|
||||||
/// <returns>对应的工具实例</returns>
|
/// <returns>对应的工具实例</returns>
|
||||||
public TUtility GetUtility<TUtility>() where TUtility : class, IUtility => _mContainer.Get<TUtility>();
|
public TUtility GetUtility<TUtility>() where TUtility : class, IUtility
|
||||||
|
{
|
||||||
|
return _mContainer.Get<TUtility>();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 发送一个带返回结果的命令请求
|
/// 发送一个带返回结果的命令请求
|
||||||
@ -180,14 +176,77 @@ public abstract class Architecture<T> : IArchitecture where T : Architecture<T>,
|
|||||||
/// <typeparam name="TResult">命令执行后的返回值类型</typeparam>
|
/// <typeparam name="TResult">命令执行后的返回值类型</typeparam>
|
||||||
/// <param name="command">要发送的命令对象</param>
|
/// <param name="command">要发送的命令对象</param>
|
||||||
/// <returns>命令执行的结果</returns>
|
/// <returns>命令执行的结果</returns>
|
||||||
public TResult SendCommand<TResult>(ICommand<TResult> command) => ExecuteCommand(command);
|
public TResult SendCommand<TResult>(ICommand<TResult> command)
|
||||||
|
{
|
||||||
|
return ExecuteCommand(command);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 发送一个无返回结果的命令请求
|
/// 发送一个无返回结果的命令请求
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TCommand">命令的具体类型</typeparam>
|
/// <typeparam name="TCommand">命令的具体类型</typeparam>
|
||||||
/// <param name="command">要发送的命令对象</param>
|
/// <param name="command">要发送的命令对象</param>
|
||||||
public void SendCommand<TCommand>(TCommand command) where TCommand : ICommand => ExecuteCommand(command);
|
public void SendCommand<TCommand>(TCommand command) where TCommand : ICommand
|
||||||
|
{
|
||||||
|
ExecuteCommand(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发起一次查询请求并获得其结果
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TResult">查询结果的数据类型</typeparam>
|
||||||
|
/// <param name="query">要发起的查询对象</param>
|
||||||
|
/// <returns>查询得到的结果数据</returns>
|
||||||
|
public TResult SendQuery<TResult>(IQuery<TResult> query)
|
||||||
|
{
|
||||||
|
return DoQuery(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发布一个默认构造的新事件对象
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TEvent">事件类型</typeparam>
|
||||||
|
public void SendEvent<TEvent>() where TEvent : new()
|
||||||
|
{
|
||||||
|
_mTypeEventSystem.Send<TEvent>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发布一个具体的事件对象
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TEvent">事件类型</typeparam>
|
||||||
|
/// <param name="e">要发布的事件实例</param>
|
||||||
|
public void SendEvent<TEvent>(TEvent e)
|
||||||
|
{
|
||||||
|
_mTypeEventSystem.Send(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 订阅某个特定类型的事件
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TEvent">事件类型</typeparam>
|
||||||
|
/// <param name="onEvent">当事件发生时触发的动作</param>
|
||||||
|
/// <returns>可用于取消订阅的对象</returns>
|
||||||
|
public IUnRegister RegisterEvent<TEvent>(Action<TEvent> onEvent)
|
||||||
|
{
|
||||||
|
return _mTypeEventSystem.Register(onEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 取消对某类型事件的监听
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TEvent">事件类型</typeparam>
|
||||||
|
/// <param name="onEvent">之前绑定的事件处理器</param>
|
||||||
|
public void UnRegisterEvent<TEvent>(Action<TEvent> onEvent)
|
||||||
|
{
|
||||||
|
_mTypeEventSystem.UnRegister(onEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 抽象初始化方法,由子类重写以进行自定义初始化操作
|
||||||
|
/// </summary>
|
||||||
|
protected abstract void Init();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 执行一个带返回结果的命令
|
/// 执行一个带返回结果的命令
|
||||||
@ -211,14 +270,6 @@ public abstract class Architecture<T> : IArchitecture where T : Architecture<T>,
|
|||||||
command.Execute();
|
command.Execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 发起一次查询请求并获得其结果
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TResult">查询结果的数据类型</typeparam>
|
|
||||||
/// <param name="query">要发起的查询对象</param>
|
|
||||||
/// <returns>查询得到的结果数据</returns>
|
|
||||||
public TResult SendQuery<TResult>(IQuery<TResult> query) => DoQuery(query);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 实际执行查询逻辑的方法
|
/// 实际执行查询逻辑的方法
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -230,37 +281,4 @@ public abstract class Architecture<T> : IArchitecture where T : Architecture<T>,
|
|||||||
query.SetArchitecture(this);
|
query.SetArchitecture(this);
|
||||||
return query.Do();
|
return query.Do();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 类型化事件系统,负责事件的发布与订阅管理
|
|
||||||
/// </summary>
|
|
||||||
private readonly TypeEventSystem _mTypeEventSystem = new();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 发布一个默认构造的新事件对象
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TEvent">事件类型</typeparam>
|
|
||||||
public void SendEvent<TEvent>() where TEvent : new() => _mTypeEventSystem.Send<TEvent>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 发布一个具体的事件对象
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TEvent">事件类型</typeparam>
|
|
||||||
/// <param name="e">要发布的事件实例</param>
|
|
||||||
public void SendEvent<TEvent>(TEvent e) => _mTypeEventSystem.Send(e);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 订阅某个特定类型的事件
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TEvent">事件类型</typeparam>
|
|
||||||
/// <param name="onEvent">当事件发生时触发的动作</param>
|
|
||||||
/// <returns>可用于取消订阅的对象</returns>
|
|
||||||
public IUnRegister RegisterEvent<TEvent>(Action<TEvent> onEvent) => _mTypeEventSystem.Register(onEvent);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 取消对某类型事件的监听
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TEvent">事件类型</typeparam>
|
|
||||||
/// <param name="onEvent">之前绑定的事件处理器</param>
|
|
||||||
public void UnRegisterEvent<TEvent>(Action<TEvent> onEvent) => _mTypeEventSystem.UnRegister(onEvent);
|
|
||||||
}
|
}
|
||||||
@ -11,6 +11,7 @@ Architecture 包是整个框架的核心,提供了基于 MVC 架构模式的
|
|||||||
架构接口,定义了框架的核心功能契约。
|
架构接口,定义了框架的核心功能契约。
|
||||||
|
|
||||||
**主要职责:**
|
**主要职责:**
|
||||||
|
|
||||||
- 组件注册:注册 System、Model、Utility
|
- 组件注册:注册 System、Model、Utility
|
||||||
- 组件获取:从容器中获取已注册的组件
|
- 组件获取:从容器中获取已注册的组件
|
||||||
- 命令处理:发送并执行命令
|
- 命令处理:发送并执行命令
|
||||||
@ -49,6 +50,7 @@ void UnRegisterEvent<T>(Action<T> onEvent);
|
|||||||
架构基类,实现了 [`IArchitecture`](IArchitecture.cs) 接口,提供完整的架构功能实现。
|
架构基类,实现了 [`IArchitecture`](IArchitecture.cs) 接口,提供完整的架构功能实现。
|
||||||
|
|
||||||
**特性:**
|
**特性:**
|
||||||
|
|
||||||
- **单例模式**:使用泛型和 `Lazy<T>` 确保全局唯一实例
|
- **单例模式**:使用泛型和 `Lazy<T>` 确保全局唯一实例
|
||||||
- **线程安全**:采用 `LazyThreadSafetyMode.ExecutionAndPublication` 保证多线程安全
|
- **线程安全**:采用 `LazyThreadSafetyMode.ExecutionAndPublication` 保证多线程安全
|
||||||
- **生命周期管理**:自动管理 System 和 Model 的初始化顺序
|
- **生命周期管理**:自动管理 System 和 Model 的初始化顺序
|
||||||
@ -56,6 +58,7 @@ void UnRegisterEvent<T>(Action<T> onEvent);
|
|||||||
- **事件系统**:集成类型化事件系统,支持类型安全的事件通信
|
- **事件系统**:集成类型化事件系统,支持类型安全的事件通信
|
||||||
|
|
||||||
**初始化流程:**
|
**初始化流程:**
|
||||||
|
|
||||||
1. 创建架构实例
|
1. 创建架构实例
|
||||||
2. 调用用户自定义的 `Init()` 方法
|
2. 调用用户自定义的 `Init()` 方法
|
||||||
3. 执行注册的补丁逻辑(`OnRegisterPatch`)
|
3. 执行注册的补丁逻辑(`OnRegisterPatch`)
|
||||||
@ -133,18 +136,23 @@ GameArchitecture.Interface.RegisterSystem(newSystem);
|
|||||||
## 设计模式
|
## 设计模式
|
||||||
|
|
||||||
### 单例模式
|
### 单例模式
|
||||||
|
|
||||||
通过泛型约束和 `Lazy<T>` 实现类型安全的单例。
|
通过泛型约束和 `Lazy<T>` 实现类型安全的单例。
|
||||||
|
|
||||||
### 依赖注入(IoC)
|
### 依赖注入(IoC)
|
||||||
|
|
||||||
使用内置 IoC 容器管理组件生命周期和依赖关系。
|
使用内置 IoC 容器管理组件生命周期和依赖关系。
|
||||||
|
|
||||||
### 命令模式
|
### 命令模式
|
||||||
|
|
||||||
通过 [`ICommand`](../command/ICommand.cs) 封装所有用户操作。
|
通过 [`ICommand`](../command/ICommand.cs) 封装所有用户操作。
|
||||||
|
|
||||||
### 查询模式(CQRS)
|
### 查询模式(CQRS)
|
||||||
|
|
||||||
通过 [`IQuery<T>`](../query/IQuery.cs) 分离查询和命令操作。
|
通过 [`IQuery<T>`](../query/IQuery.cs) 分离查询和命令操作。
|
||||||
|
|
||||||
### 观察者模式
|
### 观察者模式
|
||||||
|
|
||||||
通过事件系统实现组件间的松耦合通信。
|
通过事件系统实现组件间的松耦合通信。
|
||||||
|
|
||||||
## 最佳实践
|
## 最佳实践
|
||||||
|
|||||||
@ -14,18 +14,27 @@ public abstract class AbstractCommand : ICommand
|
|||||||
/// 获取命令所属的架构实例
|
/// 获取命令所属的架构实例
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>IArchitecture 架构接口实例</returns>
|
/// <returns>IArchitecture 架构接口实例</returns>
|
||||||
IArchitecture IBelongToArchitecture.GetArchitecture() => _mArchitecture;
|
IArchitecture IBelongToArchitecture.GetArchitecture()
|
||||||
|
{
|
||||||
|
return _mArchitecture;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置命令所属的架构实例
|
/// 设置命令所属的架构实例
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="architecture">要设置的架构实例</param>
|
/// <param name="architecture">要设置的架构实例</param>
|
||||||
void ICanSetArchitecture.SetArchitecture(IArchitecture architecture) => _mArchitecture = architecture;
|
void ICanSetArchitecture.SetArchitecture(IArchitecture architecture)
|
||||||
|
{
|
||||||
|
_mArchitecture = architecture;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 执行命令,调用抽象方法 OnExecute 来实现具体逻辑
|
/// 执行命令,调用抽象方法 OnExecute 来实现具体逻辑
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void ICommand.Execute() => OnExecute();
|
void ICommand.Execute()
|
||||||
|
{
|
||||||
|
OnExecute();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 抽象方法,由子类实现具体的命令执行逻辑
|
/// 抽象方法,由子类实现具体的命令执行逻辑
|
||||||
@ -45,19 +54,28 @@ public abstract class AbstractCommand<TResult> : ICommand<TResult>
|
|||||||
/// 获取命令所属的架构实例
|
/// 获取命令所属的架构实例
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>IArchitecture 架构接口实例</returns>
|
/// <returns>IArchitecture 架构接口实例</returns>
|
||||||
IArchitecture IBelongToArchitecture.GetArchitecture() => _mArchitecture;
|
IArchitecture IBelongToArchitecture.GetArchitecture()
|
||||||
|
{
|
||||||
|
return _mArchitecture;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置命令所属的架构实例
|
/// 设置命令所属的架构实例
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="architecture">要设置的架构实例</param>
|
/// <param name="architecture">要设置的架构实例</param>
|
||||||
void ICanSetArchitecture.SetArchitecture(IArchitecture architecture) => _mArchitecture = architecture;
|
void ICanSetArchitecture.SetArchitecture(IArchitecture architecture)
|
||||||
|
{
|
||||||
|
_mArchitecture = architecture;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 执行命令,调用抽象方法 OnExecute 来实现具体逻辑并返回结果
|
/// 执行命令,调用抽象方法 OnExecute 来实现具体逻辑并返回结果
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>TResult 类型的执行结果</returns>
|
/// <returns>TResult 类型的执行结果</returns>
|
||||||
TResult ICommand<TResult>.Execute() => OnExecute();
|
TResult ICommand<TResult>.Execute()
|
||||||
|
{
|
||||||
|
return OnExecute();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 抽象方法,由子类实现具体的命令执行逻辑
|
/// 抽象方法,由子类实现具体的命令执行逻辑
|
||||||
|
|||||||
@ -11,6 +11,7 @@ Command 包实现了命令模式(Command Pattern),用于封装用户操作
|
|||||||
无返回值命令接口,定义了命令的基本契约。
|
无返回值命令接口,定义了命令的基本契约。
|
||||||
|
|
||||||
**继承的能力接口:**
|
**继承的能力接口:**
|
||||||
|
|
||||||
- [`ICanSetArchitecture`](../rule/ICanSetArchitecture.cs) - 可设置架构
|
- [`ICanSetArchitecture`](../rule/ICanSetArchitecture.cs) - 可设置架构
|
||||||
- [`ICanGetSystem`](../system/ICanGetSystem.cs) - 可获取系统
|
- [`ICanGetSystem`](../system/ICanGetSystem.cs) - 可获取系统
|
||||||
- [`ICanGetModel`](../model/ICanGetModel.cs) - 可获取模型
|
- [`ICanGetModel`](../model/ICanGetModel.cs) - 可获取模型
|
||||||
@ -20,6 +21,7 @@ Command 包实现了命令模式(Command Pattern),用于封装用户操作
|
|||||||
- [`ICanSendQuery`](../query/ICanSendQuery.cs) - 可发送查询
|
- [`ICanSendQuery`](../query/ICanSendQuery.cs) - 可发送查询
|
||||||
|
|
||||||
**核心方法:**
|
**核心方法:**
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
void Execute(); // 执行命令
|
void Execute(); // 执行命令
|
||||||
```
|
```
|
||||||
@ -29,6 +31,7 @@ void Execute(); // 执行命令
|
|||||||
带返回值的命令接口,用于需要返回执行结果的命令。
|
带返回值的命令接口,用于需要返回执行结果的命令。
|
||||||
|
|
||||||
**核心方法:**
|
**核心方法:**
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
TResult Execute(); // 执行命令并返回结果
|
TResult Execute(); // 执行命令并返回结果
|
||||||
```
|
```
|
||||||
@ -232,12 +235,14 @@ public class LoginCommand : AbstractCommand<bool>
|
|||||||
## 命令 vs 系统方法
|
## 命令 vs 系统方法
|
||||||
|
|
||||||
**何时使用命令:**
|
**何时使用命令:**
|
||||||
|
|
||||||
- 需要参数化操作
|
- 需要参数化操作
|
||||||
- 需要记录操作历史(用于撤销/重做)
|
- 需要记录操作历史(用于撤销/重做)
|
||||||
- 操作需要跨多个系统协调
|
- 操作需要跨多个系统协调
|
||||||
- 用户触发的离散操作
|
- 用户触发的离散操作
|
||||||
|
|
||||||
**何时使用系统方法:**
|
**何时使用系统方法:**
|
||||||
|
|
||||||
- 持续运行的逻辑(如每帧更新)
|
- 持续运行的逻辑(如每帧更新)
|
||||||
- 系统内部的私有逻辑
|
- 系统内部的私有逻辑
|
||||||
- 不需要外部调用的功能
|
- 不需要外部调用的功能
|
||||||
|
|||||||
@ -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) - 可发送命令
|
- [`ICanSendCommand`](../command/ICanSendCommand.cs) - 可发送命令
|
||||||
- [`ICanGetSystem`](../system/ICanGetSystem.cs) - 可获取系统
|
- [`ICanGetSystem`](../system/ICanGetSystem.cs) - 可获取系统
|
||||||
- [`ICanGetModel`](../model/ICanGetModel.cs) - 可获取模型
|
- [`ICanGetModel`](../model/ICanGetModel.cs) - 可获取模型
|
||||||
@ -21,6 +23,7 @@ Controller 包定义了控制器(Controller)的接口规范。控制器是 M
|
|||||||
**能力说明:**
|
**能力说明:**
|
||||||
|
|
||||||
控制器拥有框架中最全面的能力集合,可以:
|
控制器拥有框架中最全面的能力集合,可以:
|
||||||
|
|
||||||
1. 发送命令执行业务逻辑
|
1. 发送命令执行业务逻辑
|
||||||
2. 获取系统调用服务
|
2. 获取系统调用服务
|
||||||
3. 获取模型读写数据
|
3. 获取模型读写数据
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
namespace GFramework.Core.events;
|
namespace GFramework.Core.events;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 默认注销器类,用于执行注销操作
|
/// 默认注销器类,用于执行注销操作
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -22,10 +22,16 @@ public class EasyEvent
|
|||||||
/// 注销已注册的事件回调函数
|
/// 注销已注册的事件回调函数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="onEvent">要注销的事件回调函数</param>
|
/// <param name="onEvent">要注销的事件回调函数</param>
|
||||||
public void UnRegister(Action onEvent) => _mOnEvent -= onEvent;
|
public void UnRegister(Action onEvent)
|
||||||
|
{
|
||||||
|
_mOnEvent -= onEvent;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 触发所有已注册的事件回调函数
|
/// 触发所有已注册的事件回调函数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Trigger() => _mOnEvent?.Invoke();
|
public void Trigger()
|
||||||
|
{
|
||||||
|
_mOnEvent?.Invoke();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -13,6 +13,22 @@ public class EasyEvent<T> : IEasyEvent
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private Action<T> _mOnEvent = e => { };
|
private Action<T> _mOnEvent = e => { };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 显式实现 IEasyEvent 接口中的 Register 方法。
|
||||||
|
/// 允许使用无参 Action 来订阅当前带参事件。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="onEvent">无参事件处理方法。</param>
|
||||||
|
/// <returns>IUnRegister 对象,用于稍后注销该事件监听器。</returns>
|
||||||
|
IUnRegister IEasyEvent.Register(Action onEvent)
|
||||||
|
{
|
||||||
|
return Register(Action);
|
||||||
|
|
||||||
|
void Action(T _)
|
||||||
|
{
|
||||||
|
onEvent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 注册一个事件监听器,并返回可用于取消注册的对象。
|
/// 注册一个事件监听器,并返回可用于取消注册的对象。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -28,24 +44,18 @@ public class EasyEvent<T> : IEasyEvent
|
|||||||
/// 取消指定的事件监听器。
|
/// 取消指定的事件监听器。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="onEvent">需要被注销的事件处理方法。</param>
|
/// <param name="onEvent">需要被注销的事件处理方法。</param>
|
||||||
public void UnRegister(Action<T> onEvent) => _mOnEvent -= onEvent;
|
public void UnRegister(Action<T> onEvent)
|
||||||
|
{
|
||||||
|
_mOnEvent -= onEvent;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 触发所有已注册的事件处理程序,并传递参数 t。
|
/// 触发所有已注册的事件处理程序,并传递参数 t。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="t">传递给事件处理程序的参数。</param>
|
/// <param name="t">传递给事件处理程序的参数。</param>
|
||||||
public void Trigger(T t) => _mOnEvent?.Invoke(t);
|
public void Trigger(T t)
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 显式实现 IEasyEvent 接口中的 Register 方法。
|
|
||||||
/// 允许使用无参 Action 来订阅当前带参事件。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="onEvent">无参事件处理方法。</param>
|
|
||||||
/// <returns>IUnRegister 对象,用于稍后注销该事件监听器。</returns>
|
|
||||||
IUnRegister IEasyEvent.Register(Action onEvent)
|
|
||||||
{
|
{
|
||||||
return Register(Action);
|
_mOnEvent?.Invoke(t);
|
||||||
void Action(T _) => onEvent();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,6 +73,22 @@ public class EasyEvent<T, TK> : IEasyEvent
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private Action<T, TK> _mOnEvent = (_, _) => { };
|
private Action<T, TK> _mOnEvent = (_, _) => { };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 显式实现 IEasyEvent 接口中的 Register 方法。
|
||||||
|
/// 允许使用无参 Action 来订阅当前带参事件。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="onEvent">无参事件处理方法。</param>
|
||||||
|
/// <returns>IUnRegister 对象,用于稍后注销该事件监听器。</returns>
|
||||||
|
IUnRegister IEasyEvent.Register(Action onEvent)
|
||||||
|
{
|
||||||
|
return Register(Action);
|
||||||
|
|
||||||
|
void Action(T _, TK __)
|
||||||
|
{
|
||||||
|
onEvent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 注册一个接受两个参数的事件监听器,并返回可用于取消注册的对象。
|
/// 注册一个接受两个参数的事件监听器,并返回可用于取消注册的对象。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -78,25 +104,19 @@ public class EasyEvent<T, TK> : IEasyEvent
|
|||||||
/// 取消指定的双参数事件监听器。
|
/// 取消指定的双参数事件监听器。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="onEvent">需要被注销的事件处理方法。</param>
|
/// <param name="onEvent">需要被注销的事件处理方法。</param>
|
||||||
public void UnRegister(Action<T, TK> onEvent) => _mOnEvent -= onEvent;
|
public void UnRegister(Action<T, TK> onEvent)
|
||||||
|
{
|
||||||
|
_mOnEvent -= onEvent;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 触发所有已注册的事件处理程序,并传递参数 t 和 k。
|
/// 触发所有已注册的事件处理程序,并传递参数 t 和 k。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="t">第一个参数。</param>
|
/// <param name="t">第一个参数。</param>
|
||||||
/// <param name="k">第二个参数。</param>
|
/// <param name="k">第二个参数。</param>
|
||||||
public void Trigger(T t, TK k) => _mOnEvent?.Invoke(t, k);
|
public void Trigger(T t, TK k)
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 显式实现 IEasyEvent 接口中的 Register 方法。
|
|
||||||
/// 允许使用无参 Action 来订阅当前带参事件。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="onEvent">无参事件处理方法。</param>
|
|
||||||
/// <returns>IUnRegister 对象,用于稍后注销该事件监听器。</returns>
|
|
||||||
IUnRegister IEasyEvent.Register(Action onEvent)
|
|
||||||
{
|
{
|
||||||
return Register(Action);
|
_mOnEvent?.Invoke(t, k);
|
||||||
void Action(T _, TK __) => onEvent();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,6 +135,22 @@ public class EasyEvent<T, TK, TS> : IEasyEvent
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private Action<T, TK, TS> _mOnEvent = (_, _, _) => { };
|
private Action<T, TK, TS> _mOnEvent = (_, _, _) => { };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 显式实现 IEasyEvent 接口中的 Register 方法。
|
||||||
|
/// 允许使用无参 Action 来订阅当前带参事件。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="onEvent">无参事件处理方法。</param>
|
||||||
|
/// <returns>IUnRegister 对象,用于稍后注销该事件监听器。</returns>
|
||||||
|
IUnRegister IEasyEvent.Register(Action onEvent)
|
||||||
|
{
|
||||||
|
return Register(Action);
|
||||||
|
|
||||||
|
void Action(T _, TK __, TS ___)
|
||||||
|
{
|
||||||
|
onEvent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 注册一个接受三个参数的事件监听器,并返回可用于取消注册的对象。
|
/// 注册一个接受三个参数的事件监听器,并返回可用于取消注册的对象。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -130,7 +166,10 @@ public class EasyEvent<T, TK, TS> : IEasyEvent
|
|||||||
/// 取消指定的三参数事件监听器。
|
/// 取消指定的三参数事件监听器。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="onEvent">需要被注销的事件处理方法。</param>
|
/// <param name="onEvent">需要被注销的事件处理方法。</param>
|
||||||
public void UnRegister(Action<T, TK, TS> onEvent) => _mOnEvent -= onEvent;
|
public void UnRegister(Action<T, TK, TS> onEvent)
|
||||||
|
{
|
||||||
|
_mOnEvent -= onEvent;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 触发所有已注册的事件处理程序,并传递参数 t、k 和 s。
|
/// 触发所有已注册的事件处理程序,并传递参数 t、k 和 s。
|
||||||
@ -138,17 +177,8 @@ public class EasyEvent<T, TK, TS> : IEasyEvent
|
|||||||
/// <param name="t">第一个参数。</param>
|
/// <param name="t">第一个参数。</param>
|
||||||
/// <param name="k">第二个参数。</param>
|
/// <param name="k">第二个参数。</param>
|
||||||
/// <param name="s">第三个参数。</param>
|
/// <param name="s">第三个参数。</param>
|
||||||
public void Trigger(T t, TK k, TS s) => _mOnEvent?.Invoke(t, k, s);
|
public void Trigger(T t, TK k, TS s)
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 显式实现 IEasyEvent 接口中的 Register 方法。
|
|
||||||
/// 允许使用无参 Action 来订阅当前带参事件。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="onEvent">无参事件处理方法。</param>
|
|
||||||
/// <returns>IUnRegister 对象,用于稍后注销该事件监听器。</returns>
|
|
||||||
IUnRegister IEasyEvent.Register(Action onEvent)
|
|
||||||
{
|
{
|
||||||
return Register(Action);
|
_mOnEvent?.Invoke(t, k, s);
|
||||||
void Action(T _, TK __, TS ___) => onEvent();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -11,29 +11,38 @@ public class EasyEvents
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private static readonly EasyEvents MGlobalEvents = new();
|
private static readonly EasyEvents MGlobalEvents = new();
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取指定类型的全局事件实例
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">事件类型,必须实现IEasyEvent接口</typeparam>
|
|
||||||
/// <returns>指定类型的事件实例,如果未注册则返回默认值</returns>
|
|
||||||
public static T Get<T>() where T : IEasyEvent => MGlobalEvents.GetEvent<T>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 注册指定类型的全局事件
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">事件类型,必须实现IEasyEvent接口且具有无参构造函数</typeparam>
|
|
||||||
public static void Register<T>() where T : IEasyEvent, new() => MGlobalEvents.AddEvent<T>();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 存储事件类型与事件实例映射关系的字典
|
/// 存储事件类型与事件实例映射关系的字典
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly Dictionary<Type, IEasyEvent> _mTypeEvents = new();
|
private readonly Dictionary<Type, IEasyEvent> _mTypeEvents = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取指定类型的全局事件实例
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">事件类型,必须实现IEasyEvent接口</typeparam>
|
||||||
|
/// <returns>指定类型的事件实例,如果未注册则返回默认值</returns>
|
||||||
|
public static T Get<T>() where T : IEasyEvent
|
||||||
|
{
|
||||||
|
return MGlobalEvents.GetEvent<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 注册指定类型的全局事件
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">事件类型,必须实现IEasyEvent接口且具有无参构造函数</typeparam>
|
||||||
|
public static void Register<T>() where T : IEasyEvent, new()
|
||||||
|
{
|
||||||
|
MGlobalEvents.AddEvent<T>();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 添加指定类型的事件到事件字典中
|
/// 添加指定类型的事件到事件字典中
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">事件类型,必须实现IEasyEvent接口且具有无参构造函数</typeparam>
|
/// <typeparam name="T">事件类型,必须实现IEasyEvent接口且具有无参构造函数</typeparam>
|
||||||
public void AddEvent<T>() where T : IEasyEvent, new() => _mTypeEvents.Add(typeof(T), new T());
|
public void AddEvent<T>() where T : IEasyEvent, new()
|
||||||
|
{
|
||||||
|
_mTypeEvents.Add(typeof(T), new T());
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取指定类型的事件实例
|
/// 获取指定类型的事件实例
|
||||||
@ -54,10 +63,7 @@ public class EasyEvents
|
|||||||
{
|
{
|
||||||
var eType = typeof(T);
|
var eType = typeof(T);
|
||||||
// 尝试从字典中获取事件实例
|
// 尝试从字典中获取事件实例
|
||||||
if (_mTypeEvents.TryGetValue(eType, out var e))
|
if (_mTypeEvents.TryGetValue(eType, out var e)) return (T)e;
|
||||||
{
|
|
||||||
return (T)e;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果不存在则创建新实例并添加到字典中
|
// 如果不存在则创建新实例并添加到字典中
|
||||||
var t = new T();
|
var t = new T();
|
||||||
|
|||||||
@ -7,6 +7,13 @@ namespace GFramework.Core.events;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class OrEvent : IUnRegisterList
|
public class OrEvent : IUnRegisterList
|
||||||
{
|
{
|
||||||
|
private Action _mOnEvent = () => { };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取取消注册列表
|
||||||
|
/// </summary>
|
||||||
|
public List<IUnRegister> UnregisterList { get; } = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 将指定的事件与当前OrEvent进行或逻辑组合
|
/// 将指定的事件与当前OrEvent进行或逻辑组合
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -18,8 +25,6 @@ public class OrEvent : IUnRegisterList
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Action _mOnEvent = () => { };
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 注册事件处理函数
|
/// 注册事件处理函数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -44,10 +49,8 @@ public class OrEvent : IUnRegisterList
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 触发所有已注册的事件处理函数
|
/// 触发所有已注册的事件处理函数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void Trigger() => _mOnEvent?.Invoke();
|
private void Trigger()
|
||||||
|
{
|
||||||
/// <summary>
|
_mOnEvent?.Invoke();
|
||||||
/// 获取取消注册列表
|
}
|
||||||
/// </summary>
|
|
||||||
public List<IUnRegister> UnregisterList { get; } = new List<IUnRegister>();
|
|
||||||
}
|
}
|
||||||
@ -11,6 +11,7 @@ Events 包提供了一套完整的事件系统,实现了观察者模式(Obse
|
|||||||
基础事件接口,定义了事件注册的基本功能。
|
基础事件接口,定义了事件注册的基本功能。
|
||||||
|
|
||||||
**核心方法:**
|
**核心方法:**
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
IUnRegister Register(Action onEvent); // 注册事件处理函数
|
IUnRegister Register(Action onEvent); // 注册事件处理函数
|
||||||
```
|
```
|
||||||
@ -20,6 +21,7 @@ IUnRegister Register(Action onEvent); // 注册事件处理函数
|
|||||||
注销接口,用于取消事件注册。
|
注销接口,用于取消事件注册。
|
||||||
|
|
||||||
**核心方法:**
|
**核心方法:**
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
void UnRegister(); // 执行注销操作
|
void UnRegister(); // 执行注销操作
|
||||||
```
|
```
|
||||||
@ -29,6 +31,7 @@ void UnRegister(); // 执行注销操作
|
|||||||
注销列表接口,用于批量管理注销对象。
|
注销列表接口,用于批量管理注销对象。
|
||||||
|
|
||||||
**属性:**
|
**属性:**
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
List<IUnRegister> UnregisterList { get; } // 获取注销列表
|
List<IUnRegister> UnregisterList { get; } // 获取注销列表
|
||||||
```
|
```
|
||||||
@ -487,7 +490,7 @@ public override void _Ready()
|
|||||||
## 事件 vs 其他通信方式
|
## 事件 vs 其他通信方式
|
||||||
|
|
||||||
| 方式 | 适用场景 | 优点 | 缺点 |
|
| 方式 | 适用场景 | 优点 | 缺点 |
|
||||||
|------|---------|------|------|
|
|----------------------|--------------|-----------|---------|
|
||||||
| **Event** | 状态变化通知、跨模块通信 | 松耦合、一对多 | 难以追踪调用链 |
|
| **Event** | 状态变化通知、跨模块通信 | 松耦合、一对多 | 难以追踪调用链 |
|
||||||
| **Command** | 执行操作、修改状态 | 封装逻辑、可撤销 | 单向通信 |
|
| **Command** | 执行操作、修改状态 | 封装逻辑、可撤销 | 单向通信 |
|
||||||
| **Query** | 查询数据 | 职责清晰、有返回值 | 同步调用 |
|
| **Query** | 查询数据 | 职责清晰、有返回值 | 同步调用 |
|
||||||
|
|||||||
@ -5,15 +5,23 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class TypeEventSystem
|
public class TypeEventSystem
|
||||||
{
|
{
|
||||||
|
public static readonly TypeEventSystem Global = new();
|
||||||
private readonly EasyEvents _mEvents = new();
|
private readonly EasyEvents _mEvents = new();
|
||||||
|
|
||||||
public static readonly TypeEventSystem Global = new();
|
public void Send<T>() where T : new()
|
||||||
|
{
|
||||||
|
_mEvents.GetEvent<EasyEvent<T>>()?.Trigger(new T());
|
||||||
|
}
|
||||||
|
|
||||||
public void Send<T>() where T : new() => _mEvents.GetEvent<EasyEvent<T>>()?.Trigger(new T());
|
public void Send<T>(T e)
|
||||||
|
{
|
||||||
|
_mEvents.GetEvent<EasyEvent<T>>()?.Trigger(e);
|
||||||
|
}
|
||||||
|
|
||||||
public void Send<T>(T e) => _mEvents.GetEvent<EasyEvent<T>>()?.Trigger(e);
|
public IUnRegister Register<T>(Action<T> onEvent)
|
||||||
|
{
|
||||||
public IUnRegister Register<T>(Action<T> onEvent) => _mEvents.GetOrAddEvent<EasyEvent<T>>().Register(onEvent);
|
return _mEvents.GetOrAddEvent<EasyEvent<T>>().Register(onEvent);
|
||||||
|
}
|
||||||
|
|
||||||
public void UnRegister<T>(Action<T> onEvent)
|
public void UnRegister<T>(Action<T> onEvent)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
namespace GFramework.Core.events;
|
namespace GFramework.Core.events;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 取消注册列表类,用于管理多个需要取消注册的对象
|
/// 取消注册列表类,用于管理多个需要取消注册的对象
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -8,6 +7,11 @@ public class UnRegisterList : IUnRegisterList
|
|||||||
{
|
{
|
||||||
private readonly List<IUnRegister> _unRegisterList = [];
|
private readonly List<IUnRegister> _unRegisterList = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取取消注册列表的只读属性
|
||||||
|
/// </summary>
|
||||||
|
public List<IUnRegister> UnregisterList { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 向取消注册列表中添加一个新的可取消注册对象
|
/// 向取消注册列表中添加一个新的可取消注册对象
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -23,17 +27,9 @@ public class UnRegisterList : IUnRegisterList
|
|||||||
public void UnRegisterAll()
|
public void UnRegisterAll()
|
||||||
{
|
{
|
||||||
// 遍历所有注册项并执行取消注册
|
// 遍历所有注册项并执行取消注册
|
||||||
foreach (var t in _unRegisterList)
|
foreach (var t in _unRegisterList) t.UnRegister();
|
||||||
{
|
|
||||||
t.UnRegister();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 清空列表
|
// 清空列表
|
||||||
_unRegisterList.Clear();
|
_unRegisterList.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取取消注册列表的只读属性
|
|
||||||
/// </summary>
|
|
||||||
public List<IUnRegister> UnregisterList { get; }
|
|
||||||
}
|
}
|
||||||
@ -15,8 +15,10 @@ public static class CanGetModelExtension
|
|||||||
/// <typeparam name="T">要获取的模型类型,必须实现IModel接口</typeparam>
|
/// <typeparam name="T">要获取的模型类型,必须实现IModel接口</typeparam>
|
||||||
/// <param name="self">实现ICanGetModel接口的对象实例</param>
|
/// <param name="self">实现ICanGetModel接口的对象实例</param>
|
||||||
/// <returns>指定类型的模型实例</returns>
|
/// <returns>指定类型的模型实例</returns>
|
||||||
public static T GetModel<T>(this ICanGetModel self) where T : class, IModel =>
|
public static T GetModel<T>(this ICanGetModel self) where T : class, IModel
|
||||||
self.GetArchitecture().GetModel<T>();
|
{
|
||||||
|
return self.GetArchitecture().GetModel<T>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -30,8 +32,10 @@ public static class CanGetSystemExtension
|
|||||||
/// <typeparam name="T">要获取的系统类型,必须实现ISystem接口</typeparam>
|
/// <typeparam name="T">要获取的系统类型,必须实现ISystem接口</typeparam>
|
||||||
/// <param name="self">实现ICanGetSystem接口的对象实例</param>
|
/// <param name="self">实现ICanGetSystem接口的对象实例</param>
|
||||||
/// <returns>指定类型的系统实例</returns>
|
/// <returns>指定类型的系统实例</returns>
|
||||||
public static T GetSystem<T>(this ICanGetSystem self) where T : class, ISystem =>
|
public static T GetSystem<T>(this ICanGetSystem self) where T : class, ISystem
|
||||||
self.GetArchitecture().GetSystem<T>();
|
{
|
||||||
|
return self.GetArchitecture().GetSystem<T>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -45,6 +49,8 @@ public static class CanGetUtilityExtension
|
|||||||
/// <typeparam name="T">要获取的工具类型,必须实现IUtility接口</typeparam>
|
/// <typeparam name="T">要获取的工具类型,必须实现IUtility接口</typeparam>
|
||||||
/// <param name="self">实现ICanGetUtility接口的对象实例</param>
|
/// <param name="self">实现ICanGetUtility接口的对象实例</param>
|
||||||
/// <returns>指定类型的工具实例</returns>
|
/// <returns>指定类型的工具实例</returns>
|
||||||
public static T GetUtility<T>(this ICanGetUtility self) where T : class, IUtility =>
|
public static T GetUtility<T>(this ICanGetUtility self) where T : class, IUtility
|
||||||
self.GetArchitecture().GetUtility<T>();
|
{
|
||||||
|
return self.GetArchitecture().GetUtility<T>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -14,8 +14,10 @@ public static class CanRegisterEventExtensions
|
|||||||
/// <param name="self">实现ICanRegisterEvent接口的对象实例</param>
|
/// <param name="self">实现ICanRegisterEvent接口的对象实例</param>
|
||||||
/// <param name="onEvent">事件处理回调函数</param>
|
/// <param name="onEvent">事件处理回调函数</param>
|
||||||
/// <returns>返回事件注销器接口,可用于后续注销事件</returns>
|
/// <returns>返回事件注销器接口,可用于后续注销事件</returns>
|
||||||
public static IUnRegister RegisterEvent<T>(this ICanRegisterEvent self, Action<T> onEvent) =>
|
public static IUnRegister RegisterEvent<T>(this ICanRegisterEvent self, Action<T> onEvent)
|
||||||
self.GetArchitecture().RegisterEvent(onEvent);
|
{
|
||||||
|
return self.GetArchitecture().RegisterEvent(onEvent);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 注销指定类型的事件处理函数
|
/// 注销指定类型的事件处理函数
|
||||||
@ -23,6 +25,8 @@ public static class CanRegisterEventExtensions
|
|||||||
/// <typeparam name="T">事件数据类型</typeparam>
|
/// <typeparam name="T">事件数据类型</typeparam>
|
||||||
/// <param name="self">实现ICanRegisterEvent接口的对象实例</param>
|
/// <param name="self">实现ICanRegisterEvent接口的对象实例</param>
|
||||||
/// <param name="onEvent">要注销的事件处理回调函数</param>
|
/// <param name="onEvent">要注销的事件处理回调函数</param>
|
||||||
public static void UnRegisterEvent<T>(this ICanRegisterEvent self, Action<T> onEvent) =>
|
public static void UnRegisterEvent<T>(this ICanRegisterEvent self, Action<T> onEvent)
|
||||||
|
{
|
||||||
self.GetArchitecture().UnRegisterEvent(onEvent);
|
self.GetArchitecture().UnRegisterEvent(onEvent);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@ -14,8 +14,10 @@ public static class CanSendCommandExtension
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">命令类型,必须实现ICommand接口且具有无参构造函数</typeparam>
|
/// <typeparam name="T">命令类型,必须实现ICommand接口且具有无参构造函数</typeparam>
|
||||||
/// <param name="self">实现ICanSendCommand接口的对象实例</param>
|
/// <param name="self">实现ICanSendCommand接口的对象实例</param>
|
||||||
public static void SendCommand<T>(this ICanSendCommand self) where T : ICommand, new() =>
|
public static void SendCommand<T>(this ICanSendCommand self) where T : ICommand, new()
|
||||||
|
{
|
||||||
self.GetArchitecture().SendCommand(new T());
|
self.GetArchitecture().SendCommand(new T());
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 发送指定的命令实例
|
/// 发送指定的命令实例
|
||||||
@ -23,8 +25,10 @@ public static class CanSendCommandExtension
|
|||||||
/// <typeparam name="T">命令类型,必须实现ICommand接口</typeparam>
|
/// <typeparam name="T">命令类型,必须实现ICommand接口</typeparam>
|
||||||
/// <param name="self">实现ICanSendCommand接口的对象实例</param>
|
/// <param name="self">实现ICanSendCommand接口的对象实例</param>
|
||||||
/// <param name="command">要发送的命令实例</param>
|
/// <param name="command">要发送的命令实例</param>
|
||||||
public static void SendCommand<T>(this ICanSendCommand self, T command) where T : ICommand =>
|
public static void SendCommand<T>(this ICanSendCommand self, T command) where T : ICommand
|
||||||
|
{
|
||||||
self.GetArchitecture().SendCommand(command);
|
self.GetArchitecture().SendCommand(command);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 发送带有返回值的命令并获取执行结果
|
/// 发送带有返回值的命令并获取执行结果
|
||||||
@ -33,8 +37,10 @@ public static class CanSendCommandExtension
|
|||||||
/// <param name="self">实现ICanSendCommand接口的对象实例</param>
|
/// <param name="self">实现ICanSendCommand接口的对象实例</param>
|
||||||
/// <param name="command">要发送的命令实例,必须实现ICommand<TResult>接口</param>
|
/// <param name="command">要发送的命令实例,必须实现ICommand<TResult>接口</param>
|
||||||
/// <returns>命令执行后的返回结果</returns>
|
/// <returns>命令执行后的返回结果</returns>
|
||||||
public static TResult SendCommand<TResult>(this ICanSendCommand self, ICommand<TResult> command) =>
|
public static TResult SendCommand<TResult>(this ICanSendCommand self, ICommand<TResult> command)
|
||||||
self.GetArchitecture().SendCommand(command);
|
{
|
||||||
|
return self.GetArchitecture().SendCommand(command);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -47,8 +53,10 @@ public static class CanSendEventExtension
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">事件类型,必须具有无参构造函数</typeparam>
|
/// <typeparam name="T">事件类型,必须具有无参构造函数</typeparam>
|
||||||
/// <param name="self">实现ICanSendEvent接口的对象实例</param>
|
/// <param name="self">实现ICanSendEvent接口的对象实例</param>
|
||||||
public static void SendEvent<T>(this ICanSendEvent self) where T : new() =>
|
public static void SendEvent<T>(this ICanSendEvent self) where T : new()
|
||||||
|
{
|
||||||
self.GetArchitecture().SendEvent<T>();
|
self.GetArchitecture().SendEvent<T>();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 发送指定的事件实例
|
/// 发送指定的事件实例
|
||||||
@ -56,7 +64,10 @@ public static class CanSendEventExtension
|
|||||||
/// <typeparam name="T">事件类型</typeparam>
|
/// <typeparam name="T">事件类型</typeparam>
|
||||||
/// <param name="self">实现ICanSendEvent接口的对象实例</param>
|
/// <param name="self">实现ICanSendEvent接口的对象实例</param>
|
||||||
/// <param name="e">要发送的事件实例</param>
|
/// <param name="e">要发送的事件实例</param>
|
||||||
public static void SendEvent<T>(this ICanSendEvent self, T e) => self.GetArchitecture().SendEvent(e);
|
public static void SendEvent<T>(this ICanSendEvent self, T e)
|
||||||
|
{
|
||||||
|
self.GetArchitecture().SendEvent(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -71,6 +82,8 @@ public static class CanSendQueryExtension
|
|||||||
/// <param name="self">实现ICanSendQuery接口的对象实例</param>
|
/// <param name="self">实现ICanSendQuery接口的对象实例</param>
|
||||||
/// <param name="query">要发送的查询实例,必须实现IQuery<TResult>接口</param>
|
/// <param name="query">要发送的查询实例,必须实现IQuery<TResult>接口</param>
|
||||||
/// <returns>查询操作的返回结果</returns>
|
/// <returns>查询操作的返回结果</returns>
|
||||||
public static TResult SendQuery<TResult>(this ICanSendQuery self, IQuery<TResult> query) =>
|
public static TResult SendQuery<TResult>(this ICanSendQuery self, IQuery<TResult> query)
|
||||||
self.GetArchitecture().SendQuery(query);
|
{
|
||||||
|
return self.GetArchitecture().SendQuery(query);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -13,5 +13,8 @@ public static class OrEventExtensions
|
|||||||
/// <param name="self">当前的IEasyEvent事件实例</param>
|
/// <param name="self">当前的IEasyEvent事件实例</param>
|
||||||
/// <param name="e">要与当前事件进行或运算的另一个IEasyEvent事件实例</param>
|
/// <param name="e">要与当前事件进行或运算的另一个IEasyEvent事件实例</param>
|
||||||
/// <returns>返回一个新的OrEvent实例,表示两个事件的或运算结果</returns>
|
/// <returns>返回一个新的OrEvent实例,表示两个事件的或运算结果</returns>
|
||||||
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -8,7 +8,8 @@ Extensions 包提供了一系列扩展方法,简化了框架各个接口的使
|
|||||||
|
|
||||||
### 1. 获取组件扩展 ([`CanGetExtensions.cs`](CanGetExtensions.cs))
|
### 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
|
#### CanGetModelExtension
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace GFramework.Core.extensions;
|
namespace GFramework.Core.extensions;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 扩展方法类,为IUnRegister和IUnRegisterList接口提供便捷的注册和注销功能
|
/// 扩展方法类,为IUnRegister和IUnRegisterList接口提供便捷的注册和注销功能
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -13,8 +12,10 @@ public static class UnRegisterListExtension
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="self">要添加的可注销对象</param>
|
/// <param name="self">要添加的可注销对象</param>
|
||||||
/// <param name="unRegisterList">目标注销列表</param>
|
/// <param name="unRegisterList">目标注销列表</param>
|
||||||
public static void AddToUnregisterList(this IUnRegister self, IUnRegisterList unRegisterList) =>
|
public static void AddToUnregisterList(this IUnRegister self, IUnRegisterList unRegisterList)
|
||||||
|
{
|
||||||
unRegisterList.UnregisterList.Add(self);
|
unRegisterList.UnregisterList.Add(self);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 注销列表中的所有对象并清空列表
|
/// 注销列表中的所有对象并清空列表
|
||||||
@ -23,10 +24,7 @@ public static class UnRegisterListExtension
|
|||||||
public static void UnRegisterAll(this IUnRegisterList self)
|
public static void UnRegisterAll(this IUnRegisterList self)
|
||||||
{
|
{
|
||||||
// 遍历注销列表中的所有对象并执行注销操作
|
// 遍历注销列表中的所有对象并执行注销操作
|
||||||
foreach (var unRegister in self.UnregisterList)
|
foreach (var unRegister in self.UnregisterList) unRegister.UnRegister();
|
||||||
{
|
|
||||||
unRegister.UnRegister();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 清空注销列表
|
// 清空注销列表
|
||||||
self.UnregisterList.Clear();
|
self.UnregisterList.Clear();
|
||||||
|
|||||||
@ -29,10 +29,7 @@ public class IocContainer
|
|||||||
var key = typeof(T);
|
var key = typeof(T);
|
||||||
|
|
||||||
// 尝试从字典中获取实例
|
// 尝试从字典中获取实例
|
||||||
if (_mInstances.TryGetValue(key, out var retInstance))
|
if (_mInstances.TryGetValue(key, out var retInstance)) return retInstance as T;
|
||||||
{
|
|
||||||
return retInstance as T;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
## 概述
|
## 概述
|
||||||
|
|
||||||
IoC(Inversion of Control,控制反转)包提供了一个轻量级的依赖注入容器,用于管理框架中各种组件的注册和获取。通过 IoC 容器,可以实现组件间的解耦,便于测试和维护。
|
IoC(Inversion of Control,控制反转)包提供了一个轻量级的依赖注入容器,用于管理框架中各种组件的注册和获取。通过 IoC
|
||||||
|
容器,可以实现组件间的解耦,便于测试和维护。
|
||||||
|
|
||||||
## 核心类
|
## 核心类
|
||||||
|
|
||||||
@ -11,6 +12,7 @@ IoC(Inversion of Control,控制反转)包提供了一个轻量级的依赖
|
|||||||
IoC 容器类,负责管理对象的注册和获取。
|
IoC 容器类,负责管理对象的注册和获取。
|
||||||
|
|
||||||
**主要功能:**
|
**主要功能:**
|
||||||
|
|
||||||
- 注册实例到容器
|
- 注册实例到容器
|
||||||
- 从容器中获取实例
|
- 从容器中获取实例
|
||||||
- 类型安全的依赖管理
|
- 类型安全的依赖管理
|
||||||
@ -26,6 +28,7 @@ public void Register<T>(T instance)
|
|||||||
```
|
```
|
||||||
|
|
||||||
**参数:**
|
**参数:**
|
||||||
|
|
||||||
- `instance`: 要注册的实例对象
|
- `instance`: 要注册的实例对象
|
||||||
|
|
||||||
**使用示例:**
|
**使用示例:**
|
||||||
@ -48,6 +51,7 @@ public T Get<T>() where T : class
|
|||||||
```
|
```
|
||||||
|
|
||||||
**返回值:**
|
**返回值:**
|
||||||
|
|
||||||
- 返回指定类型的实例,如果未找到则返回 `null`
|
- 返回指定类型的实例,如果未找到则返回 `null`
|
||||||
|
|
||||||
**使用示例:**
|
**使用示例:**
|
||||||
@ -294,6 +298,7 @@ var service = container.Get<MyService>();
|
|||||||
```
|
```
|
||||||
|
|
||||||
**特点:**
|
**特点:**
|
||||||
|
|
||||||
- ✅ 简单易用
|
- ✅ 简单易用
|
||||||
- ✅ 性能高
|
- ✅ 性能高
|
||||||
- ❌ 不支持构造函数注入
|
- ❌ 不支持构造函数注入
|
||||||
@ -314,6 +319,7 @@ var controller = container.Resolve<MyController>();
|
|||||||
```
|
```
|
||||||
|
|
||||||
**特点:**
|
**特点:**
|
||||||
|
|
||||||
- ✅ 自动依赖注入
|
- ✅ 自动依赖注入
|
||||||
- ✅ 生命周期管理
|
- ✅ 生命周期管理
|
||||||
- ✅ 复杂场景支持
|
- ✅ 复杂场景支持
|
||||||
|
|||||||
@ -16,18 +16,27 @@ public abstract class AbstractModel : IModel
|
|||||||
/// 获取模型所属的架构实例
|
/// 获取模型所属的架构实例
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>返回当前模型关联的架构对象</returns>
|
/// <returns>返回当前模型关联的架构对象</returns>
|
||||||
public IArchitecture GetArchitecture() => Architecture;
|
public IArchitecture GetArchitecture()
|
||||||
|
{
|
||||||
|
return Architecture;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置模型所属的架构实例
|
/// 设置模型所属的架构实例
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="architecture">要关联到此模型的架构实例</param>
|
/// <param name="architecture">要关联到此模型的架构实例</param>
|
||||||
public void SetArchitecture(IArchitecture architecture) => Architecture = architecture;
|
public void SetArchitecture(IArchitecture architecture)
|
||||||
|
{
|
||||||
|
Architecture = architecture;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 初始化模型,调用抽象方法OnInit执行具体初始化逻辑
|
/// 初始化模型,调用抽象方法OnInit执行具体初始化逻辑
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void IModel.Init() => OnInit();
|
void IModel.Init()
|
||||||
|
{
|
||||||
|
OnInit();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 抽象初始化方法,由子类实现具体的初始化逻辑
|
/// 抽象初始化方法,由子类实现具体的初始化逻辑
|
||||||
|
|||||||
@ -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) - 可设置架构引用
|
- [`ICanSetArchitecture`](../rule/ICanSetArchitecture.cs) - 可设置架构引用
|
||||||
- [`ICanGetUtility`](../utility/ICanGetUtility.cs) - 可获取工具类
|
- [`ICanGetUtility`](../utility/ICanGetUtility.cs) - 可获取工具类
|
||||||
- [`ICanSendEvent`](../events/ICanSendEvent.cs) - 可发送事件
|
- [`ICanSendEvent`](../events/ICanSendEvent.cs) - 可发送事件
|
||||||
|
|
||||||
**核心方法:**
|
**核心方法:**
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
void Init(); // 初始化模型
|
void Init(); // 初始化模型
|
||||||
```
|
```
|
||||||
|
|||||||
@ -2,7 +2,6 @@ using GFramework.Core.events;
|
|||||||
|
|
||||||
namespace GFramework.Core.property;
|
namespace GFramework.Core.property;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 可绑定属性类,用于实现数据绑定功能
|
/// 可绑定属性类,用于实现数据绑定功能
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -10,6 +9,7 @@ namespace GFramework.Core.property;
|
|||||||
/// <param name="defaultValue">属性的默认值</param>
|
/// <param name="defaultValue">属性的默认值</param>
|
||||||
public class BindableProperty<T>(T defaultValue = default!) : IBindableProperty<T>
|
public class BindableProperty<T>(T defaultValue = default!) : IBindableProperty<T>
|
||||||
{
|
{
|
||||||
|
private Action<T>? _mOnValueChanged;
|
||||||
protected T MValue = defaultValue;
|
protected T MValue = defaultValue;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -17,17 +17,6 @@ public class BindableProperty<T>(T defaultValue = default!) : IBindableProperty<
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static Func<T, T, bool> Comparer { get; set; } = (a, b) => a!.Equals(b)!;
|
public static Func<T, T, bool> Comparer { get; set; } = (a, b) => a!.Equals(b)!;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 设置自定义比较器
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="comparer">用于比较两个值是否相等的函数</param>
|
|
||||||
/// <returns>当前可绑定属性实例</returns>
|
|
||||||
public BindableProperty<T> WithComparer(Func<T, T, bool> comparer)
|
|
||||||
{
|
|
||||||
Comparer = comparer;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取或设置属性值,当值发生变化时会触发注册的回调事件
|
/// 获取或设置属性值,当值发生变化时会触发注册的回调事件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -50,25 +39,14 @@ public class BindableProperty<T>(T defaultValue = default!) : IBindableProperty<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 设置属性值的虚方法,可在子类中重写
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="newValue">新的属性值</param>
|
|
||||||
protected virtual void SetValue(T newValue) => MValue = newValue;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取属性值的虚方法,可在子类中重写
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>当前属性值</returns>
|
|
||||||
protected virtual T GetValue() => MValue;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 直接设置属性值而不触发事件
|
/// 直接设置属性值而不触发事件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="newValue">新的属性值</param>
|
/// <param name="newValue">新的属性值</param>
|
||||||
public void SetValueWithoutEvent(T newValue) => MValue = newValue;
|
public void SetValueWithoutEvent(T newValue)
|
||||||
|
{
|
||||||
private Action<T>? _mOnValueChanged = null;
|
MValue = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 注册属性值变化事件回调
|
/// 注册属性值变化事件回调
|
||||||
@ -96,7 +74,10 @@ public class BindableProperty<T>(T defaultValue = default!) : IBindableProperty<
|
|||||||
/// 取消注册属性值变化事件回调
|
/// 取消注册属性值变化事件回调
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="onValueChanged">要取消注册的回调函数</param>
|
/// <param name="onValueChanged">要取消注册的回调函数</param>
|
||||||
public void UnRegister(Action<T> onValueChanged) => _mOnValueChanged -= onValueChanged;
|
public void UnRegister(Action<T> onValueChanged)
|
||||||
|
{
|
||||||
|
_mOnValueChanged -= onValueChanged;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 实现IEasyEvent接口的注册方法,将无参事件转换为有参事件处理
|
/// 实现IEasyEvent接口的注册方法,将无参事件转换为有参事件处理
|
||||||
@ -106,15 +87,48 @@ public class BindableProperty<T>(T defaultValue = default!) : IBindableProperty<
|
|||||||
IUnRegister IEasyEvent.Register(Action onEvent)
|
IUnRegister IEasyEvent.Register(Action onEvent)
|
||||||
{
|
{
|
||||||
return Register(Action);
|
return Register(Action);
|
||||||
|
|
||||||
void Action(T _)
|
void Action(T _)
|
||||||
{
|
{
|
||||||
onEvent();
|
onEvent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置自定义比较器
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="comparer">用于比较两个值是否相等的函数</param>
|
||||||
|
/// <returns>当前可绑定属性实例</returns>
|
||||||
|
public BindableProperty<T> WithComparer(Func<T, T, bool> comparer)
|
||||||
|
{
|
||||||
|
Comparer = comparer;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置属性值的虚方法,可在子类中重写
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="newValue">新的属性值</param>
|
||||||
|
protected virtual void SetValue(T newValue)
|
||||||
|
{
|
||||||
|
MValue = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取属性值的虚方法,可在子类中重写
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>当前属性值</returns>
|
||||||
|
protected virtual T GetValue()
|
||||||
|
{
|
||||||
|
return MValue;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 返回属性值的字符串表示形式
|
/// 返回属性值的字符串表示形式
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>属性值的字符串表示</returns>
|
/// <returns>属性值的字符串表示</returns>
|
||||||
public override string ToString() => Value?.ToString() ?? string.Empty;
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Value?.ToString() ?? string.Empty;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -2,7 +2,6 @@ using GFramework.Core.events;
|
|||||||
|
|
||||||
namespace GFramework.Core.property;
|
namespace GFramework.Core.property;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 可绑定属性注销器类,用于取消注册可绑定属性的值变化监听
|
/// 可绑定属性注销器类,用于取消注册可绑定属性的值变化监听
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -2,7 +2,6 @@ using GFramework.Core.events;
|
|||||||
|
|
||||||
namespace GFramework.Core.property;
|
namespace GFramework.Core.property;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 只读可绑定属性接口,提供属性值的读取和变更监听功能
|
/// 只读可绑定属性接口,提供属性值的读取和变更监听功能
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -11,6 +11,7 @@ Property 包提供了可绑定属性(BindableProperty)的实现,支持属
|
|||||||
只读可绑定属性接口,提供属性值的读取和变更监听功能。
|
只读可绑定属性接口,提供属性值的读取和变更监听功能。
|
||||||
|
|
||||||
**核心成员:**
|
**核心成员:**
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
T Value { get; } // 获取属性值
|
T Value { get; } // 获取属性值
|
||||||
IUnRegister Register(Action<T> onValueChanged); // 注册监听
|
IUnRegister Register(Action<T> onValueChanged); // 注册监听
|
||||||
@ -23,6 +24,7 @@ void UnRegister(Action<T> onValueChanged); // 取消监听
|
|||||||
可绑定属性接口,继承自只读接口,增加了修改能力。
|
可绑定属性接口,继承自只读接口,增加了修改能力。
|
||||||
|
|
||||||
**核心成员:**
|
**核心成员:**
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
new T Value { get; set; } // 可读写的属性值
|
new T Value { get; set; } // 可读写的属性值
|
||||||
void SetValueWithoutEvent(T newValue); // 设置值但不触发事件
|
void SetValueWithoutEvent(T newValue); // 设置值但不触发事件
|
||||||
|
|||||||
@ -8,29 +8,38 @@ namespace GFramework.Core.query;
|
|||||||
/// <typeparam name="T">查询结果的类型</typeparam>
|
/// <typeparam name="T">查询结果的类型</typeparam>
|
||||||
public abstract class AbstractQuery<T> : IQuery<T>
|
public abstract class AbstractQuery<T> : IQuery<T>
|
||||||
{
|
{
|
||||||
|
private IArchitecture _mArchitecture;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 执行查询操作
|
/// 执行查询操作
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>查询结果</returns>
|
/// <returns>查询结果</returns>
|
||||||
public T Do() => OnDo();
|
public T Do()
|
||||||
|
{
|
||||||
|
return OnDo();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取架构实例
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>架构实例</returns>
|
||||||
|
public IArchitecture GetArchitecture()
|
||||||
|
{
|
||||||
|
return _mArchitecture;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置架构实例
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="architecture">要设置的架构实例</param>
|
||||||
|
public void SetArchitecture(IArchitecture architecture)
|
||||||
|
{
|
||||||
|
_mArchitecture = architecture;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 抽象方法,由子类实现具体的查询逻辑
|
/// 抽象方法,由子类实现具体的查询逻辑
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>查询结果</returns>
|
/// <returns>查询结果</returns>
|
||||||
protected abstract T OnDo();
|
protected abstract T OnDo();
|
||||||
|
|
||||||
private IArchitecture _mArchitecture;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取架构实例
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>架构实例</returns>
|
|
||||||
public IArchitecture GetArchitecture() => _mArchitecture;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 设置架构实例
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="architecture">要设置的架构实例</param>
|
|
||||||
public void SetArchitecture(IArchitecture architecture) => _mArchitecture = architecture;
|
|
||||||
}
|
}
|
||||||
@ -4,7 +4,6 @@ using GFramework.Core.system;
|
|||||||
|
|
||||||
namespace GFramework.Core.query;
|
namespace GFramework.Core.query;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查询接口,定义了执行查询操作的契约
|
/// 查询接口,定义了执行查询操作的契约
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
## 概述
|
## 概述
|
||||||
|
|
||||||
Query 包实现了 CQRS(命令查询职责分离)模式中的查询部分。Query 用于封装数据查询逻辑,与 Command 不同的是,Query 有返回值且不应该修改系统状态。
|
Query 包实现了 CQRS(命令查询职责分离)模式中的查询部分。Query 用于封装数据查询逻辑,与 Command 不同的是,Query
|
||||||
|
有返回值且不应该修改系统状态。
|
||||||
|
|
||||||
## 核心接口
|
## 核心接口
|
||||||
|
|
||||||
@ -11,6 +12,7 @@ Query 包实现了 CQRS(命令查询职责分离)模式中的查询部分。
|
|||||||
标记接口,表示该类型可以发送查询。
|
标记接口,表示该类型可以发送查询。
|
||||||
|
|
||||||
**继承关系:**
|
**继承关系:**
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public interface ICanSendQuery : IBelongToArchitecture
|
public interface ICanSendQuery : IBelongToArchitecture
|
||||||
```
|
```
|
||||||
@ -20,11 +22,13 @@ public interface ICanSendQuery : IBelongToArchitecture
|
|||||||
查询接口,定义了查询的基本契约。
|
查询接口,定义了查询的基本契约。
|
||||||
|
|
||||||
**核心成员:**
|
**核心成员:**
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
TResult Do(); // 执行查询并返回结果
|
TResult Do(); // 执行查询并返回结果
|
||||||
```
|
```
|
||||||
|
|
||||||
**继承的能力:**
|
**继承的能力:**
|
||||||
|
|
||||||
- `ICanSetArchitecture` - 可设置架构
|
- `ICanSetArchitecture` - 可设置架构
|
||||||
- `ICanGetModel` - 可获取 Model
|
- `ICanGetModel` - 可获取 Model
|
||||||
- `ICanGetSystem` - 可获取 System
|
- `ICanGetSystem` - 可获取 System
|
||||||
@ -37,6 +41,7 @@ TResult Do(); // 执行查询并返回结果
|
|||||||
抽象查询基类,提供了查询的基础实现。
|
抽象查询基类,提供了查询的基础实现。
|
||||||
|
|
||||||
**使用方式:**
|
**使用方式:**
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public abstract class AbstractQuery<T> : IQuery<T>
|
public abstract class AbstractQuery<T> : IQuery<T>
|
||||||
{
|
{
|
||||||
@ -287,11 +292,13 @@ public class EnemyAISystem : AbstractSystem
|
|||||||
## Command vs Query
|
## Command vs Query
|
||||||
|
|
||||||
### Command(命令)
|
### Command(命令)
|
||||||
|
|
||||||
- **用途**:修改系统状态
|
- **用途**:修改系统状态
|
||||||
- **返回值**:无返回值(void)
|
- **返回值**:无返回值(void)
|
||||||
- **示例**:购买物品、造成伤害、升级角色
|
- **示例**:购买物品、造成伤害、升级角色
|
||||||
|
|
||||||
### Query(查询)
|
### Query(查询)
|
||||||
|
|
||||||
- **用途**:读取数据,不修改状态
|
- **用途**:读取数据,不修改状态
|
||||||
- **返回值**:有返回值
|
- **返回值**:有返回值
|
||||||
- **示例**:获取金币数量、检查技能冷却、查询玩家位置
|
- **示例**:获取金币数量、检查技能冷却、查询玩家位置
|
||||||
|
|||||||
@ -2,7 +2,6 @@ using GFramework.Core.architecture;
|
|||||||
|
|
||||||
namespace GFramework.Core.rule;
|
namespace GFramework.Core.rule;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 定义一个接口,用于标识某个对象属于特定的架构体系。
|
/// 定义一个接口,用于标识某个对象属于特定的架构体系。
|
||||||
/// 实现此接口的对象可以通过GetArchitecture方法获取其所属的架构实例。
|
/// 实现此接口的对象可以通过GetArchitecture方法获取其所属的架构实例。
|
||||||
|
|||||||
@ -11,6 +11,7 @@ Rule 包定义了框架的核心规则接口,这些接口规定了框架各个
|
|||||||
标记接口,表示某个对象属于特定的架构体系。
|
标记接口,表示某个对象属于特定的架构体系。
|
||||||
|
|
||||||
**接口定义:**
|
**接口定义:**
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public interface IBelongToArchitecture
|
public interface IBelongToArchitecture
|
||||||
{
|
{
|
||||||
@ -19,6 +20,7 @@ public interface IBelongToArchitecture
|
|||||||
```
|
```
|
||||||
|
|
||||||
**实现此接口的类型:**
|
**实现此接口的类型:**
|
||||||
|
|
||||||
- Controller
|
- Controller
|
||||||
- System
|
- System
|
||||||
- Model
|
- Model
|
||||||
@ -34,6 +36,7 @@ public interface IBelongToArchitecture
|
|||||||
定义可以设置架构实例的能力。
|
定义可以设置架构实例的能力。
|
||||||
|
|
||||||
**接口定义:**
|
**接口定义:**
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public interface ICanSetArchitecture
|
public interface ICanSetArchitecture
|
||||||
{
|
{
|
||||||
@ -42,6 +45,7 @@ public interface ICanSetArchitecture
|
|||||||
```
|
```
|
||||||
|
|
||||||
**实现此接口的类型:**
|
**实现此接口的类型:**
|
||||||
|
|
||||||
- Command
|
- Command
|
||||||
- Query
|
- Query
|
||||||
|
|
||||||
|
|||||||
@ -15,18 +15,27 @@ public abstract class AbstractSystem : ISystem
|
|||||||
/// 获取当前系统所属的架构实例
|
/// 获取当前系统所属的架构实例
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>返回系统关联的架构对象</returns>
|
/// <returns>返回系统关联的架构对象</returns>
|
||||||
IArchitecture IBelongToArchitecture.GetArchitecture() => _mArchitecture;
|
IArchitecture IBelongToArchitecture.GetArchitecture()
|
||||||
|
{
|
||||||
|
return _mArchitecture;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置系统所属的架构实例
|
/// 设置系统所属的架构实例
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="architecture">要关联的架构对象</param>
|
/// <param name="architecture">要关联的架构对象</param>
|
||||||
void ICanSetArchitecture.SetArchitecture(IArchitecture architecture) => _mArchitecture = architecture;
|
void ICanSetArchitecture.SetArchitecture(IArchitecture architecture)
|
||||||
|
{
|
||||||
|
_mArchitecture = architecture;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 系统初始化方法,调用抽象初始化方法
|
/// 系统初始化方法,调用抽象初始化方法
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void ISystem.Init() => OnInit();
|
void ISystem.Init()
|
||||||
|
{
|
||||||
|
OnInit();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 抽象初始化方法,由子类实现具体的初始化逻辑
|
/// 抽象初始化方法,由子类实现具体的初始化逻辑
|
||||||
|
|||||||
@ -11,6 +11,7 @@ System 包定义了业务逻辑层(Business Logic Layer)。System 负责处
|
|||||||
标记接口,表示该类型可以获取其他 System。
|
标记接口,表示该类型可以获取其他 System。
|
||||||
|
|
||||||
**继承关系:**
|
**继承关系:**
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public interface ICanGetSystem : IBelongToArchitecture
|
public interface ICanGetSystem : IBelongToArchitecture
|
||||||
```
|
```
|
||||||
@ -20,11 +21,13 @@ public interface ICanGetSystem : IBelongToArchitecture
|
|||||||
System 接口,定义了系统的基本行为。
|
System 接口,定义了系统的基本行为。
|
||||||
|
|
||||||
**核心成员:**
|
**核心成员:**
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
void Init(); // 系统初始化方法
|
void Init(); // 系统初始化方法
|
||||||
```
|
```
|
||||||
|
|
||||||
**继承的能力:**
|
**继承的能力:**
|
||||||
|
|
||||||
- `ICanSetArchitecture` - 可设置架构
|
- `ICanSetArchitecture` - 可设置架构
|
||||||
- `ICanGetModel` - 可获取 Model
|
- `ICanGetModel` - 可获取 Model
|
||||||
- `ICanGetUtility` - 可获取 Utility
|
- `ICanGetUtility` - 可获取 Utility
|
||||||
@ -39,6 +42,7 @@ void Init(); // 系统初始化方法
|
|||||||
抽象 System 基类,提供了 System 的基础实现。
|
抽象 System 基类,提供了 System 的基础实现。
|
||||||
|
|
||||||
**使用方式:**
|
**使用方式:**
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public abstract class AbstractSystem : ISystem
|
public abstract class AbstractSystem : ISystem
|
||||||
{
|
{
|
||||||
@ -419,11 +423,13 @@ public class GameStateSystem : AbstractSystem
|
|||||||
## System vs Model
|
## System vs Model
|
||||||
|
|
||||||
### Model(数据层)
|
### Model(数据层)
|
||||||
|
|
||||||
- **职责**:存储数据和状态
|
- **职责**:存储数据和状态
|
||||||
- **特点**:被动,等待修改
|
- **特点**:被动,等待修改
|
||||||
- **示例**:PlayerModel、InventoryModel
|
- **示例**:PlayerModel、InventoryModel
|
||||||
|
|
||||||
### System(逻辑层)
|
### System(逻辑层)
|
||||||
|
|
||||||
- **职责**:处理业务逻辑,协调 Model
|
- **职责**:处理业务逻辑,协调 Model
|
||||||
- **特点**:主动,响应事件
|
- **特点**:主动,响应事件
|
||||||
- **示例**:CombatSystem、QuestSystem
|
- **示例**:CombatSystem、QuestSystem
|
||||||
|
|||||||
@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
## 概述
|
## 概述
|
||||||
|
|
||||||
Utility 包定义了工具类层。Utility 提供无状态的辅助功能,如数学计算、文件操作、序列化等通用工具方法。与 System 不同,Utility 不依赖架构状态,是纯粹的工具函数集合。
|
Utility 包定义了工具类层。Utility 提供无状态的辅助功能,如数学计算、文件操作、序列化等通用工具方法。与 System 不同,Utility
|
||||||
|
不依赖架构状态,是纯粹的工具函数集合。
|
||||||
|
|
||||||
## 核心接口
|
## 核心接口
|
||||||
|
|
||||||
@ -11,6 +12,7 @@ Utility 包定义了工具类层。Utility 提供无状态的辅助功能,如
|
|||||||
标记接口,表示该类型可以获取 Utility。
|
标记接口,表示该类型可以获取 Utility。
|
||||||
|
|
||||||
**继承关系:**
|
**继承关系:**
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public interface ICanGetUtility : IBelongToArchitecture
|
public interface ICanGetUtility : IBelongToArchitecture
|
||||||
```
|
```
|
||||||
@ -20,6 +22,7 @@ public interface ICanGetUtility : IBelongToArchitecture
|
|||||||
Utility 标记接口,所有工具类都应实现此接口。
|
Utility 标记接口,所有工具类都应实现此接口。
|
||||||
|
|
||||||
**接口定义:**
|
**接口定义:**
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public interface IUtility
|
public interface IUtility
|
||||||
{
|
{
|
||||||
@ -419,12 +422,14 @@ public class LogUtility : IUtility
|
|||||||
## Utility vs System
|
## Utility vs System
|
||||||
|
|
||||||
### Utility(工具层)
|
### Utility(工具层)
|
||||||
|
|
||||||
- **无状态** - 不存储业务数据
|
- **无状态** - 不存储业务数据
|
||||||
- **纯函数** - 相同输入产生相同输出
|
- **纯函数** - 相同输入产生相同输出
|
||||||
- **独立性** - 不依赖架构状态
|
- **独立性** - 不依赖架构状态
|
||||||
- **可复用** - 可在多个项目中使用
|
- **可复用** - 可在多个项目中使用
|
||||||
|
|
||||||
### System(逻辑层)
|
### System(逻辑层)
|
||||||
|
|
||||||
- **有状态** - 可能存储临时状态
|
- **有状态** - 可能存储临时状态
|
||||||
- **业务逻辑** - 处理特定业务流程
|
- **业务逻辑** - 处理特定业务流程
|
||||||
- **架构依赖** - 需要访问 Model
|
- **架构依赖** - 需要访问 Model
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace GFramework.Generator.Attributes
|
namespace GFramework.Generator.Attributes
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
项目额外的简单代码生成器
|
项目额外的简单代码生成器
|
||||||
目前已有的功能
|
目前已有的功能
|
||||||
|
|
||||||
- 为枚举添加两个扩展方法方便判断枚举值
|
- 为枚举添加两个扩展方法方便判断枚举值
|
||||||
@ -5,8 +5,8 @@ using Microsoft.CodeAnalysis;
|
|||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
using Microsoft.CodeAnalysis.Text;
|
using Microsoft.CodeAnalysis.Text;
|
||||||
|
|
||||||
namespace GFramework.Generator.generator.enums
|
namespace GFramework.Generator.generator.enums;
|
||||||
{
|
|
||||||
[Generator]
|
[Generator]
|
||||||
public class EnumExtensionsGenerator : IIncrementalGenerator
|
public class EnumExtensionsGenerator : IIncrementalGenerator
|
||||||
{
|
{
|
||||||
@ -17,8 +17,8 @@ namespace GFramework.Generator.generator.enums
|
|||||||
// 1. 找到所有 EnumDeclarationSyntax 节点
|
// 1. 找到所有 EnumDeclarationSyntax 节点
|
||||||
var enumDecls = context.SyntaxProvider
|
var enumDecls = context.SyntaxProvider
|
||||||
.CreateSyntaxProvider(
|
.CreateSyntaxProvider(
|
||||||
predicate: (s, _) => s is EnumDeclarationSyntax,
|
(s, _) => s is EnumDeclarationSyntax,
|
||||||
transform: (ctx, _) =>
|
(ctx, _) =>
|
||||||
(EnumDecl: (EnumDeclarationSyntax)ctx.Node, ctx.SemanticModel))
|
(EnumDecl: (EnumDeclarationSyntax)ctx.Node, ctx.SemanticModel))
|
||||||
.Where(t => t.EnumDecl != null);
|
.Where(t => t.EnumDecl != null);
|
||||||
|
|
||||||
@ -47,7 +47,6 @@ namespace GFramework.Generator.generator.enums
|
|||||||
context.RegisterSourceOutput(enumSymbols, (spc, list) =>
|
context.RegisterSourceOutput(enumSymbols, (spc, list) =>
|
||||||
{
|
{
|
||||||
foreach (var enumSymbol in list.Select(item => item.Symbol))
|
foreach (var enumSymbol in list.Select(item => item.Symbol))
|
||||||
{
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var src = GenerateForEnum(enumSymbol);
|
var src = GenerateForEnum(enumSymbol);
|
||||||
@ -61,7 +60,6 @@ namespace GFramework.Generator.generator.enums
|
|||||||
spc.AddSource($"{enumSymbol?.Name}.EnumExtensions.Error.g.cs",
|
spc.AddSource($"{enumSymbol?.Name}.EnumExtensions.Error.g.cs",
|
||||||
SourceText.From(err, Encoding.UTF8));
|
SourceText.From(err, Encoding.UTF8));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +105,7 @@ namespace GFramework.Generator.generator.enums
|
|||||||
|
|
||||||
|
|
||||||
// 2. IsIn(params ...) 方法
|
// 2. IsIn(params ...) 方法
|
||||||
sb.AppendLine($" /// <summary>Auto-generated: 判断是否属于指定集合</summary>");
|
sb.AppendLine(" /// <summary>Auto-generated: 判断是否属于指定集合</summary>");
|
||||||
sb.AppendLine(
|
sb.AppendLine(
|
||||||
$" public static bool IsIn(this {fullEnumName} value, params {fullEnumName}[] values)");
|
$" public static bool IsIn(this {fullEnumName} value, params {fullEnumName}[] values)");
|
||||||
sb.AppendLine(" {");
|
sb.AppendLine(" {");
|
||||||
@ -122,4 +120,3 @@ namespace GFramework.Generator.generator.enums
|
|||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@ -1,7 +1,9 @@
|
|||||||
# 项目介绍
|
# 项目介绍
|
||||||
|
|
||||||
本项目参考(CV)自[QFramework](https://github.com/liangxiegame/QFramework)
|
本项目参考(CV)自[QFramework](https://github.com/liangxiegame/QFramework)
|
||||||
|
|
||||||
# 为什么要有这个项目
|
# 为什么要有这个项目
|
||||||
|
|
||||||
- 原来的项目是单文件框架,我把框架拆成多个文件,方便管理
|
- 原来的项目是单文件框架,我把框架拆成多个文件,方便管理
|
||||||
- 纯粹个人自用,要使用还是请访问[QFramework](https://github.com/liangxiegame/QFramework)
|
- 纯粹个人自用,要使用还是请访问[QFramework](https://github.com/liangxiegame/QFramework)
|
||||||
- 至于修改名字,是因为我为了方便会发布GuGet包,假设将来QFramework也要发布GuGet包,那么就会冲突了
|
- 至于修改名字,是因为我为了方便会发布GuGet包,假设将来QFramework也要发布GuGet包,那么就会冲突了
|
||||||
Loading…
x
Reference in New Issue
Block a user