mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-23 03:04:29 +08:00
- 将标题从"架构模式最佳实践"改为"架构设计模式指南" - 添加全面的架构设计模式介绍和概述 - 新增MVC模式详细说明,包括概念、GFramework实现示例和最佳实践 - 新增MVVM模式详细说明,包括概念、GFramework实现示例和最佳实践 - 新增命令模式详细说明,包括概念、实现示例和撤销功能支持 - 新增查询模式详细说明,包括CQRS概念和复杂查询示例 - 新增事件驱动模式详细说明,包括事件定义和监听实现 - 新增依赖注入模式详细说明,包括构造函数注入示例 - 新增服务定位器模式详细说明,包括与依赖注入对比 - 新增对象池模式详细说明,包括通用对象池实现 - 新增状态模式详细说明,包括异步状态和状态机系统 - 补充模式选择与组合建议,针对小型、中型、大型项目提供不同方案 - 更新代码示例中的泛型语法格式,统一使用尖括号表示法
21 KiB
21 KiB
版本迁移指南
本文档提供 GFramework 不同版本之间的迁移指导,帮助开发者平滑升级到新版本。
概述
迁移指南的使用
本迁移指南旨在帮助开发者:
- 了解版本间的重大变更:明确不同版本之间的 API 变化和行为差异
- 规划迁移路径:根据项目实际情况选择合适的迁移策略
- 减少迁移风险:通过详细的步骤说明和代码示例降低升级风险
- 快速定位问题:提供常见问题的解决方案和回滚策略
阅读建议
- 确认当前版本:查看项目中使用的 GFramework 版本号
- 查看目标版本:确定要升级到的目标版本
- 阅读相关章节:重点关注涉及的版本迁移章节
- 测试验证:在测试环境中完成迁移并充分测试
- 逐步升级:对于跨多个大版本的升级,建议分步进行
版本兼容性
版本号说明
GFramework 遵循 语义化版本 规范:
主版本号.次版本号.修订号 (MAJOR.MINOR.PATCH)
- 主版本号(MAJOR):不兼容的 API 变更
- 次版本号(MINOR):向后兼容的功能新增
- 修订号(PATCH):向后兼容的问题修正
兼容性矩阵
| 源版本 | 目标版本 | 兼容性 | 迁移难度 | 说明 |
|---|---|---|---|---|
| 0.0.x | 0.0.y | ✅ 完全兼容 | 低 | 修订版本,直接升级 |
| 0.0.x | 1.0.0 | ⚠️ 部分兼容 | 中 | 需要代码调整 |
| 0.x.x | 1.x.x | ❌ 不兼容 | 高 | 重大变更,需要重构 |
| 1.x.x | 1.y.y | ✅ 向后兼容 | 低 | 次版本升级,可能有废弃警告 |
| 1.x.x | 2.0.0 | ❌ 不兼容 | 高 | 重大变更,需要重构 |
.NET 版本支持
| GFramework 版本 | .NET 8.0 | .NET 9.0 | .NET 10.0 |
|---|---|---|---|
| 0.0.x | ✅ | ✅ | ✅ |
| 1.0.x | ✅ | ✅ | ✅ |
| 2.0.x | ❌ | ✅ | ✅ |
Godot 版本支持
| GFramework 版本 | Godot 4.3 | Godot 4.4 | Godot 4.5 | Godot 4.6+ |
|---|---|---|---|---|
| 0.0.x | ✅ | ✅ | ✅ | ✅ |
| 1.0.x | ❌ | ✅ | ✅ | ✅ |
| 2.0.x | ❌ | ❌ | ✅ | ✅ |
从 0.x 迁移到 1.x
重大变更概述
1.0 版本是 GFramework 的第一个稳定版本,引入了多项重大变更以提升框架的稳定性、性能和可维护性。
架构层面变更
- 架构初始化方式变更:统一使用异步初始化
- 生命周期阶段调整:简化阶段流程,移除冗余阶段
- IOC 容器增强:支持作用域和生命周期管理
- 模块系统重构:引入新的模块注册机制
API 变更
- 命名空间调整:部分类型移动到新的命名空间
- 接口签名变更:部分接口方法签名调整
- 废弃 API 移除:移除 0.x 中标记为废弃的 API
- 泛型约束调整:部分泛型方法增加或调整约束
行为变更
- 事件传播机制:优化事件传播逻辑
- 协程调度策略:改进协程调度算法
- 资源管理策略:引入新的资源释放策略
迁移前准备
1. 备份项目
# 创建项目备份
git checkout -b backup-before-migration
git push origin backup-before-migration
# 或使用文件系统备份
cp -r YourProject YourProject-backup
2. 检查当前版本
# 查看当前使用的 GFramework 版本
dotnet list package | grep GFramework
3. 更新依赖工具
# 更新 .NET SDK
dotnet --version
# 更新 NuGet 客户端
dotnet nuget --version
4. 运行现有测试
# 确保所有测试通过
dotnet test
# 记录测试结果作为基准
dotnet test --logger "trx;LogFileName=baseline-tests.trx"
迁移步骤
步骤 1:更新 NuGet 包
# 更新核心包
dotnet add package GeWuYou.GFramework.Core --version 1.0.0
dotnet add package GeWuYou.GFramework.Core.Abstractions --version 1.0.0
# 更新游戏扩展包
dotnet add package GeWuYou.GFramework.Game --version 1.0.0
dotnet add package GeWuYou.GFramework.Game.Abstractions --version 1.0.0
# 更新 Godot 集成包(如果使用)
dotnet add package GeWuYou.GFramework.Godot --version 1.0.0
# 更新源码生成器
dotnet add package GeWuYou.GFramework.SourceGenerators --version 1.0.0
步骤 2:更新命名空间引用
0.x 版本:
using GFramework.Core;
using GFramework.Core.Architecture;
using GFramework.Core.Events;
1.x 版本:
using GFramework.Core.Abstractions.Architecture;
using GFramework.Core.Abstractions.Events;
using GFramework.Core.Architecture;
using GFramework.Core.Events;
步骤 3:更新架构初始化代码
0.x 版本:
public class GameArchitecture : Architecture
{
protected override void Init()
{
RegisterModel(new PlayerModel());
RegisterSystem(new GameplaySystem());
}
}
// 同步初始化
var architecture = new GameArchitecture();
architecture.Initialize();
1.x 版本:
public class GameArchitecture : Architecture
{
protected override void Init()
{
RegisterModel(new PlayerModel());
RegisterSystem(new GameplaySystem());
}
}
// 推荐使用异步初始化
var architecture = new GameArchitecture();
await architecture.InitializeAsync();
// 或者使用同步初始化(不推荐)
// architecture.Initialize();
步骤 4:更新事件注册代码
0.x 版本:
// 注册事件
this.RegisterEvent<PlayerDiedEvent>(OnPlayerDied);
// 发送事件
this.SendEvent(new PlayerDiedEvent());
1.x 版本:
// 注册事件(API 保持兼容)
this.RegisterEvent<PlayerDiedEvent>(OnPlayerDied);
// 发送事件(API 保持兼容)
this.SendEvent(new PlayerDiedEvent());
// 新增:带优先级的事件注册
this.RegisterEvent<PlayerDiedEvent>(OnPlayerDied, priority: 100);
步骤 5:更新命令和查询代码
0.x 版本:
public class MovePlayerCommand : AbstractCommand
{
public Vector2 Direction { get; set; }
protected override void OnDo()
{
// 执行逻辑
}
}
// 发送命令
this.SendCommand(new MovePlayerCommand { Direction = direction });
1.x 版本:
// 命令 API 保持兼容
public class MovePlayerCommand : AbstractCommand
{
public Vector2 Direction { get; set; }
protected override void OnDo()
{
// 执行逻辑
}
}
// 发送命令(API 保持兼容)
this.SendCommand(new MovePlayerCommand { Direction = direction });
// 新增:异步命令支持
public class LoadDataCommand : AbstractAsyncCommand
{
protected override async Task OnDoAsync()
{
await Task.Delay(100);
}
}
步骤 6:更新 IOC 容器使用
0.x 版本:
// 注册服务
RegisterUtility(new StorageUtility());
// 获取服务
var storage = this.GetUtility<StorageUtility>();
1.x 版本:
// 注册服务(API 保持兼容)
RegisterUtility(new StorageUtility());
// 获取服务(API 保持兼容)
var storage = this.GetUtility<StorageUtility>();
// 新增:按优先级获取服务
var storages = this.GetUtilities<IStorageUtility>();
var primaryStorage = storages.FirstOrDefault();
步骤 7:更新协程代码
0.x 版本:
// 启动协程
var handle = CoroutineHelper.Start(MyCoroutine());
// 等待协程
yield return new WaitForCoroutine(handle);
1.x 版本:
// 启动协程(API 保持兼容)
var handle = CoroutineHelper.Start(MyCoroutine());
// 等待协程(API 保持兼容)
yield return new WaitForCoroutine(handle);
// 新增:协程分组和优先级
var handle = CoroutineHelper.Start(
MyCoroutine(),
group: "gameplay",
priority: CoroutinePriority.High
);
API 变更详解
废弃的 API
以下 API 在 1.0 版本中已被移除:
1. 同步命令查询扩展(已废弃)
0.x 版本:
// 这些方法在 1.0 中已移除
this.SendCommandSync(command);
this.SendQuerySync(query);
1.x 版本:
// 使用标准方法
this.SendCommand(command);
this.SendQuery(query);
// 或使用异步方法
await this.SendCommandAsync(command);
await this.SendQueryAsync(query);
2. 旧版事件 API(已废弃)
0.x 版本:
// 旧版事件注册方式
EventBus.Register<MyEvent>(handler);
1.x 版本:
// 使用新的事件注册方式
this.RegisterEvent<MyEvent>(handler);
// 或使用事件总线
this.GetEventBus().Register<MyEvent>(handler);
3. 直接访问 IOC 容器(已限制)
0.x 版本:
// 直接访问容器
var container = architecture.Container;
container.Register<IService, ServiceImpl>();
1.x 版本:
// 使用架构提供的注册方法
architecture.RegisterUtility<IService>(new ServiceImpl());
// 或在 Init 方法中注册
protected override void Init()
{
RegisterUtility<IService>(new ServiceImpl());
}
新增的 API
1. 优先级支持
// 事件优先级
this.RegisterEvent<MyEvent>(handler, priority: 100);
// 服务优先级
RegisterUtility<IService>(service, priority: 10);
// 协程优先级
CoroutineHelper.Start(routine, priority: CoroutinePriority.High);
2. 异步初始化增强
// 异步初始化架构
await architecture.InitializeAsync();
// 等待架构就绪
await architecture.WaitUntilReadyAsync();
// 异步初始化组件
public class MyModel : AbstractModel, IAsyncInitializable
{
public async Task InitializeAsync()
{
await LoadDataAsync();
}
}
3. 事件过滤和统计
// 事件过滤
this.RegisterEvent<MyEvent>(handler, filter: e => e.IsValid);
// 事件统计
var stats = eventBus.GetStatistics();
Console.WriteLine($"Total events: {stats.TotalEventsSent}");
4. 协程分组管理
// 创建协程组
var handle = CoroutineHelper.Start(
routine,
group: "ui-animations"
);
// 暂停协程组
CoroutineHelper.PauseGroup("ui-animations");
// 恢复协程组
CoroutineHelper.ResumeGroup("ui-animations");
// 停止协程组
CoroutineHelper.StopGroup("ui-animations");
配置变更
架构配置
0.x 版本:
var architecture = new GameArchitecture();
1.x 版本:
// 使用配置对象
var config = new ArchitectureConfiguration
{
ArchitectureProperties = new ArchitectureProperties
{
StrictPhaseValidation = true,
AllowLateRegistration = false
},
LoggerProperties = new LoggerProperties
{
MinimumLevel = LogLevel.Information
}
};
var architecture = new GameArchitecture(configuration: config);
日志配置
0.x 版本:
// 使用默认日志
1.x 版本:
// 配置日志系统
var logConfig = new LoggingConfiguration
{
MinimumLevel = LogLevel.Debug,
Appenders = new List<ILogAppender>
{
new ConsoleAppender(),
new FileAppender("logs/game.log")
},
Filters = new List<ILogFilter>
{
new LogLevelFilter(LogLevel.Warning),
new NamespaceFilter("GFramework.*")
}
};
依赖变更
NuGet 包更新
| 包名 | 0.x 版本 | 1.x 版本 | 变更说明 |
|---|---|---|---|
| Microsoft.Extensions.DependencyInjection | 8.0.0 | 10.0.3 | 升级到最新版本 |
| Arch | 1.x | 2.1.0 | ECS 框架升级 |
| Arch.System | 1.0.x | 1.1.0 | 系统组件升级 |
包拆分
1.0 版本对包结构进行了优化:
0.x 版本:
<PackageReference Include="GeWuYou.GFramework" Version="0.0.200" />
1.x 版本:
<!-- 推荐按需引用 -->
<PackageReference Include="GeWuYou.GFramework.Core" Version="1.0.0" />
<PackageReference Include="GeWuYou.GFramework.Core.Abstractions" Version="1.0.0" />
<PackageReference Include="GeWuYou.GFramework.Game" Version="1.0.0" />
<PackageReference Include="GeWuYou.GFramework.Godot" Version="1.0.0" />
代码迁移工具
自动化迁移工具
GFramework 提供了迁移工具来自动化部分迁移工作:
# 安装迁移工具
dotnet tool install -g GFramework.MigrationTool
# 运行迁移分析
gframework-migrate analyze --project YourProject.csproj
# 执行自动迁移
gframework-migrate apply --project YourProject.csproj --target-version 1.0.0
# 生成迁移报告
gframework-migrate report --output migration-report.html
手动迁移检查清单
使用以下清单确保完整迁移:
- 更新所有 NuGet 包到 1.0.0
- 更新命名空间引用
- 替换废弃的 API
- 更新架构初始化代码
- 更新配置代码
- 运行所有单元测试
- 运行集成测试
- 执行性能测试
- 更新文档和注释
- 代码审查
测试迁移
单元测试更新
0.x 版本:
[Test]
public void TestArchitectureInit()
{
var architecture = new TestArchitecture();
architecture.Initialize();
Assert.That(architecture.CurrentPhase, Is.EqualTo(ArchitecturePhase.Ready));
}
1.x 版本:
[Test]
public async Task TestArchitectureInit()
{
var architecture = new TestArchitecture();
await architecture.InitializeAsync();
Assert.That(architecture.CurrentPhase, Is.EqualTo(ArchitecturePhase.Ready));
}
集成测试更新
0.x 版本:
[Test]
public void TestGameFlow()
{
var game = new GameArchitecture();
game.Initialize();
game.SendCommand(new StartGameCommand());
var score = game.SendQuery(new GetScoreQuery());
Assert.That(score, Is.EqualTo(0));
}
1.x 版本:
[Test]
public async Task TestGameFlow()
{
var game = new GameArchitecture();
await game.InitializeAsync();
await game.SendCommandAsync(new StartGameCommand());
var score = await game.SendQueryAsync(new GetScoreQuery());
Assert.That(score, Is.EqualTo(0));
}
常见问题
编译错误
问题 1:命名空间找不到
错误信息:
error CS0246: The type or namespace name 'IArchitecture' could not be found
解决方案:
// 添加正确的命名空间引用
using GFramework.Core.Abstractions.Architecture;
问题 2:方法签名不匹配
错误信息:
error CS1501: No overload for method 'RegisterEvent' takes 1 arguments
解决方案:
// 0.x 版本
this.RegisterEvent<MyEvent>(handler);
// 1.x 版本(兼容)
this.RegisterEvent<MyEvent>(handler);
// 1.x 版本(带优先级)
this.RegisterEvent<MyEvent>(handler, priority: 100);
问题 3:泛型约束不满足
错误信息:
error CS0311: The type 'MyType' cannot be used as type parameter 'T'
in the generic type or method. There is no implicit reference conversion
from 'MyType' to 'GFramework.Core.Abstractions.IModel'.
解决方案:
// 确保类型实现了正确的接口
public class MyModel : AbstractModel, IModel
{
// 实现
}
运行时错误
问题 1:架构未初始化
错误信息:
InvalidOperationException: Architecture is not initialized
解决方案:
// 确保在使用前初始化架构
var architecture = new GameArchitecture();
await architecture.InitializeAsync();
await architecture.WaitUntilReadyAsync();
// 然后再使用
this.SendCommand(new MyCommand());
问题 2:服务未注册
错误信息:
InvalidOperationException: Service of type 'IMyService' is not registered
解决方案:
// 在 Init 方法中注册服务
protected override void Init()
{
RegisterUtility<IMyService>(new MyServiceImpl());
}
问题 3:事件处理器未触发
问题描述: 事件发送后,注册的处理器没有被调用。
解决方案:
// 确保事件处理器正确注册
var unregister = this.RegisterEvent<MyEvent>(OnMyEvent);
// 确保在对象销毁时注销
protected override void OnDestroy()
{
unregister?.UnRegister();
}
// 检查事件类型是否匹配
this.SendEvent(new MyEvent()); // 确保类型完全一致
性能问题
问题 1:初始化时间过长
问题描述: 架构初始化耗时明显增加。
解决方案:
// 使用异步初始化
await architecture.InitializeAsync();
// 对于耗时的初始化操作,使用异步方法
public class MyModel : AbstractModel, IAsyncInitializable
{
public async Task InitializeAsync()
{
// 异步加载数据
await LoadDataAsync();
}
}
问题 2:事件处理性能下降
问题描述: 事件处理速度变慢。
解决方案:
// 使用事件过滤减少不必要的处理
this.RegisterEvent<MyEvent>(
handler,
filter: e => e.ShouldProcess
);
// 使用优先级控制处理顺序
this.RegisterEvent<MyEvent>(
criticalHandler,
priority: 100
);
兼容性问题
问题 1:Godot 版本不兼容
问题描述: 升级后在 Godot 4.3 中无法运行。
解决方案:
# GFramework 1.0 要求 Godot 4.4+
# 升级 Godot 到 4.4 或更高版本
问题 2:.NET 版本不兼容
问题描述: 项目使用 .NET 7.0,无法使用 GFramework 1.0。
解决方案:
<!-- 升级项目到 .NET 8.0 或更高版本 -->
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
回滚方案
如果迁移过程中遇到无法解决的问题,可以按以下步骤回滚:
步骤 1:恢复包版本
# 回滚到 0.x 版本
dotnet add package GeWuYou.GFramework.Core --version 0.0.200
dotnet add package GeWuYou.GFramework.Core.Abstractions --version 0.0.200
dotnet add package GeWuYou.GFramework.Game --version 0.0.200
dotnet add package GeWuYou.GFramework.Godot --version 0.0.200
步骤 2:恢复代码
# 从备份分支恢复
git checkout backup-before-migration
# 或从文件系统备份恢复
rm -rf YourProject
cp -r YourProject-backup YourProject
步骤 3:验证回滚
# 清理构建缓存
dotnet clean
rm -rf bin obj
# 重新构建
dotnet build
# 运行测试
dotnet test
步骤 4:记录问题
创建问题报告,包含:
- 遇到的具体错误
- 错误发生的环境信息
- 复现步骤
- 相关代码片段
提交到 GitHub Issues。
获取帮助
官方资源
- 文档中心:https://gewuyou.github.io/GFramework/
- GitHub 仓库:https://github.com/GeWuYou/GFramework
- 问题追踪:https://github.com/GeWuYou/GFramework/issues
- 讨论区:https://github.com/GeWuYou/GFramework/discussions
社区支持
- 在 GitHub Discussions 中提问
- 查看已有的 Issues 和 Pull Requests
- 参考示例项目和教程
商业支持
如需专业的迁移支持服务,请联系项目维护团队。
附录
A. 完整的 API 对照表
| 0.x API | 1.x API | 说明 |
|---|---|---|
architecture.Initialize() |
await architecture.InitializeAsync() |
推荐使用异步初始化 |
this.SendCommandSync() |
this.SendCommand() |
移除 Sync 后缀 |
this.SendQuerySync() |
this.SendQuery() |
移除 Sync 后缀 |
EventBus.Register() |
this.RegisterEvent() |
使用扩展方法 |
Container.Register() |
RegisterUtility() |
使用架构方法 |
B. 迁移时间估算
| 项目规模 | 预估时间 | 说明 |
|---|---|---|
| 小型(<10k 行) | 1-2 天 | 主要是包更新和测试 |
| 中型(10k-50k 行) | 3-5 天 | 需要代码审查和重构 |
| 大型(>50k 行) | 1-2 周 | 需要分模块迁移和充分测试 |
C. 相关资源
文档版本:1.0.0 最后更新:2026-03-07 许可证:Apache 2.0