Skip to content

Refactor/ecs to arch adapter#62

Merged
GeWuYou merged 7 commits into
mainfrom
refactor/ecs-to-arch-adapter
Mar 2, 2026
Merged

Refactor/ecs to arch adapter#62
GeWuYou merged 7 commits into
mainfrom
refactor/ecs-to-arch-adapter

Conversation

@GeWuYou

@GeWuYou GeWuYou commented Mar 1, 2026

Copy link
Copy Markdown
Owner

Summary by Sourcery

使用基于 Arch.Core 的 ECS 模块和适配器替换自定义的 ECS world 与系统基础设施,并更新测试和服务以采用新架构。

New Features:

  • 引入 ArchEcsModule,用于在服务模块框架中管理 Arch.Core World 的生命周期,并协调系统更新。
  • 新增 ArchSystemAdapter 基类,以将 Arch.System 系统集成到现有的框架生命周期和依赖注入(DI)容器中。

Enhancements:

  • 重构 MovementSystem,使其继承自 ArchSystemAdapter,并使用原生查询直接在 Arch.Core World 上运行。
  • PositionVelocity ECS 组件标记为顺序结构体布局,以改善互操作性并控制内存布局。
  • 当启用 ECS 时,将服务模块管理器切换为注册新的 ArchEcsModule,而不是旧的 ECS 模块。
  • 简化 ECS 单元测试和集成测试,使其直接使用 Arch.Core WorldArchEcsModule,而不再依赖已移除的自定义 ECS world 和 runner 抽象。
  • IArchitectureContext 及其测试实现中移除与 ECS 相关的方法,使该抽象与新的基于 Arch 的 ECS 集成保持一致。

Tests:

  • 更新基础、高级和集成 ECS 测试,通过 ArchEcsModule 和 Arch.Core World 验证行为,包括创建、销毁、组件操作、系统更新以及性能场景。

Chores:

  • 删除已废弃的 ECS 抽象和实现,包括 IEcsWorldIEcsSystemEcsWorldEcsSystemBaseEcsSystemRunner 以及旧的 EcsModule
Original summary in English

Summary by Sourcery

Replace the custom ECS world and system infrastructure with an Arch.Core-based ECS module and adapters, and update tests and services to use the new architecture.

New Features:

  • Introduce ArchEcsModule to manage the Arch.Core World lifecycle and coordinated system updates within the service module framework.
  • Add ArchSystemAdapter base class to integrate Arch.System systems with the existing framework lifecycle and DI container.

Enhancements:

  • Refactor MovementSystem to inherit from ArchSystemAdapter and operate directly on the Arch.Core World using native queries.
  • Mark Position and Velocity ECS components with sequential struct layout for better interop and memory layout control.
  • Switch the service module manager to register the new ArchEcsModule when ECS is enabled instead of the old ECS module.
  • Simplify ECS unit and integration tests to use Arch.Core World and ArchEcsModule directly instead of the removed custom ECS world and runner abstractions.
  • Remove ECS-related methods from IArchitectureContext and its test implementations, aligning the abstraction with the new Arch-based ECS integration.

Tests:

  • Update basic, advanced, and integration ECS tests to validate behavior through ArchEcsModule and Arch.Core World, including creation, destruction, component operations, system updates, and performance scenarios.

Chores:

  • Delete obsolete ECS abstractions and implementations, including IEcsWorld, IEcsSystem, EcsWorld, EcsSystemBase, EcsSystemRunner, and the old EcsModule.

GeWuYou added 4 commits March 1, 2026 22:08
- 将EcsModule类重命名为EcsServiceModule
- 更新构造函数名称以匹配新的类名
- 修改ModuleName属性中的类型引用
- 在服务模块管理器中更新模块实例化调用
- 移除原有的ECS基础实现和接口定义
- 添加ArchEcsModule作为新的ECS模块实现
- 创建ArchSystemAdapter基类用于桥接Arch系统
- 修改MovementSystem继承ArchSystemAdapter适配新架构
- 更新ServiceModuleManager使用新的ArchECS模块
- 移除ArchitectureContext中的ECS相关方法
- 从项目中移除对Arch包的直接依赖引用
- 为 Position 结构体添加 StructLayout 特性以确保顺序布局
- 为 Velocity 结构体添加 StructLayout 特性以确保顺序布局
- 更新 Velocity 组件的 XML 文档注释,提供更详细的描述
- 优化 Velocity 组件属性的文档注释,明确单位信息
- 添加 System.Runtime.InteropServices 命名空间引用
- 将 MovementSystem 从继承 EcsSystemBase 改为继承 ArchSystemAdapter
- 更新 MovementSystem 的初始化和更新方法以适配 Arch 架构
- 移除测试代码中的 ECS 相关接口实现和抽象层
- 将测试用例从 GFramework ECS API 迁移到 Arch 原生 API
- 更新 ECS 测试类以使用 Arch World 和实体操作方法
- 重构 ECS 模块初始化流程以支持 Arch 系统注册和管理
@sourcery-ai

sourcery-ai Bot commented Mar 1, 2026

Copy link
Copy Markdown

审查者指南(Reviewer's Guide)

将 ECS 集成从自定义的 EcsWorld/EcsSystem* 抽象重构为基于 Arch.Core 的 ArchEcsModuleArchSystemAdapter,更新测试和服务装配以使用新的架构适配器,并从架构上下文中移除旧的 ECS API。

使用 ArchEcsModule 和 ArchSystemAdapter 进行 ECS 更新的时序图

sequenceDiagram
    participant GL as GameLoop
    participant AEM as ArchEcsModule
    participant SYS as MovementSystem
    participant W as World

    GL->>AEM: Update(deltaTime)
    loop for each ArchSystemAdapter<float>
        AEM->>SYS: Update(deltaTime)
        activate SYS
        SYS->>SYS: OnUpdate(deltaTime)
        SYS->>W: Query(Position, Velocity)
        loop for each matching Entity
            W-->>SYS: ref Position, ref Velocity
            SYS->>SYS: pos.X += vel.X * deltaTime
            SYS->>SYS: pos.Y += vel.Y * deltaTime
        end
        deactivate SYS
    end
Loading

新的基于 Arch 的 ECS 集成类图

classDiagram
    direction LR

    class IServiceModule {
        <<interface>>
        +string ModuleName
        +int Priority
        +bool IsEnabled
        +void Register(IIocContainer container)
        +void Initialize()
        +ValueTask DestroyAsync()
    }

    class IIocContainer {
        <<interface>>
        +void Register(object instance)
        +T Get~T~()
        +List~T~ GetAll~T~()
    }

    class World {
        +static World Create()
        +static void Destroy(World world)
        +int Size
        +Entity Create()
        +Entity Create(Position position, Velocity velocity)
        +void Destroy(Entity entity)
        +void Clear()
        +bool IsAlive(Entity entity)
        +bool Has~T~(Entity entity)
        +ref T Get~T~(Entity entity)
        +void Add~T~(Entity entity, T component)
        +void Remove~T~(Entity entity)
    }

    class AbstractSystem {
        <<abstract>>
        +void Initialize()
        +void Destroy()
        #void OnInit()
        #void OnDestroy()
    }

    namespace Arch_System {
        class ISystem_T_ {
            <<interface>>
            +void Initialize()
            +void BeforeUpdate(T t)
            +void Update(T t)
            +void AfterUpdate(T t)
        }
    }

    class ArchSystemAdapter_T_ {
        <<abstract>>
        +World World
        +void Initialize()
        +void Destroy()
        +void Update(T t)
        #void OnInit()
        #void OnDestroy()
        #void OnArchInitialize()
        #void OnBeforeUpdate(T t)
        #void OnUpdate(T t)
        #void OnAfterUpdate(T t)
        #void OnArchDispose()
    }

    class MovementSystem {
        <<sealed>>
        -QueryDescription _query
        #void OnArchInitialize()
        #void OnUpdate(float deltaTime)
    }

    class ArchEcsModule {
        <<sealed>>
        -List~ArchSystemAdapter~float~~ _systems
        -IIocContainer _container
        -World _world
        +string ModuleName
        +int Priority
        +bool IsEnabled
        +ArchEcsModule(bool enabled)
        +void Register(IIocContainer container)
        +void Initialize()
        +ValueTask DestroyAsync()
        +void Update(float deltaTime)
    }

    class ServiceModuleManager {
        -ILogger _logger
        +void RegisterBuiltInModules(IIocContainer container, ArchitectureProperties properties)
    }

    class Position {
        <<struct>>
        +float X
        +float Y
    }

    class Velocity {
        <<struct>>
        +float X
        +float Y
    }

    IServiceModule <|.. ArchEcsModule
    AbstractSystem <|-- ArchSystemAdapter_T_
    Arch_System.ISystem_T_ <|.. ArchSystemAdapter_T_

    ArchSystemAdapter_T_ --> World : uses

    ArchSystemAdapter_float_ <|-- MovementSystem

    ArchEcsModule o-- World : owns
    ArchEcsModule o-- "*" ArchSystemAdapter_float_ : manages

    ServiceModuleManager --> ArchEcsModule : registers
    ServiceModuleManager --> IIocContainer : uses

    World --> Position : component
    World --> Velocity : component
Loading

文件级变更(File-Level Changes)

Change Details Files
使用基于 Arch.Core 的适配层和模块替换自定义 ECS world/system 实现。
  • 引入 ArchSystemAdapter<T>,用于在 Arch.System.ISystem<T> 与框架的 AbstractSystem 生命周期之间建立桥接,并通过 DI 暴露 Arch.Core.World
  • 新增 ArchEcsModule,拥有一个 Arch.Core.World,从容器解析所有 ArchSystemAdapter<float> 系统,管理它们的初始化、更新和异步销毁,并将 World 注册为服务。
  • 更新 ServiceModuleManager,在配置启用 ECS 时注册 ArchEcsModule,而不再注册旧的 EcsModule
GFramework.Core/ecs/ArchSystemAdapter.cs
GFramework.Core/ecs/ArchEcsModule.cs
GFramework.Core/services/ServiceModuleManager.cs
使 MovementSystem 适配新的 ArchSystemAdapter 和 Arch.Core World 用法。
  • MovementSystem 从继承 EcsSystemBase 改为继承 ArchSystemAdapter<float>
  • 将初始化逻辑移动到 OnArchInitialize,将更新逻辑移动到 OnUpdate,并使用 QueryDescription 直接查询 Arch.Core.World
  • 移除 PriorityEcsSystemBase 特定的生命周期逻辑,将系统简化为被适配器包装的纯 Arch 行为。
GFramework.Core/ecs/systems/MovementSystem.cs
更新 ECS 组件,使其成为对 Arch 友好的值类型。
  • PositionVelocity 结构体添加 StructLayout(LayoutKind.Sequential) 特性,以确保在 Arch ECS 中具有可预测的内存布局。
  • 略微调整 XML 文档注释,以描述它们在新的 ECS 上下文中的用途。
GFramework.Core/ecs/components/Position.cs
GFramework.Core/ecs/components/Velocity.cs
从架构上下文抽象及其测试替身中移除 ECS 特定 API。
  • IArchitectureContextArchitectureContext 中删除 GetEcsWorldRegisterEcsSystem,以反映 ECS 现在由 ArchEcsModule 驱动,而不是由上下文驱动。
  • ArchitectureServicesTestsGameContextTests 中使用的 IArchitectureContext 测试实现中移除 ECS 方法。
GFramework.Core.Abstractions/architecture/IArchitectureContext.cs
GFramework.Core/architecture/ArchitectureContext.cs
GFramework.Core.Tests/architecture/ArchitectureServicesTests.cs
GFramework.Core.Tests/architecture/GameContextTests.cs
将 ECS 测试重写为面向 Arch.Core WorldArchEcsModule,而不是旧的 EcsWorld/EcsSystemRunner API。
  • 重构基础、集成和高级 ECS 测试,使其创建并使用 MicrosoftDiContainer + ArchitectureContext,初始化 ArchEcsModule,并从容器解析 Arch.Core.World
  • 将 world/entity 断言从 EcsWorld.EntityCount/IsAlive/InternalWorld 改为 Arch.Core.World.Size/IsAlive 以及直接对 World 的组件访问。
  • ArchEcsModule.Update 和在容器中直接注册 MovementSystemArchSystemAdapter 的方式,替换基于 system-runner 的执行(EcsSystemRunnerIEcsSystem 列表、优先级)。
  • 调整或删除针对旧 API 的测试(如 EcsWorld 幂等释放、优先级顺序、GetEcsWorldEcsSystemRunner 行为),并为 ArchEcsModule 生命周期新增测试(异步销毁、无系统场景、累积更新、多实体场景)。
  • 移除测试中的日志相关设置,因为新的流程在 ECS 设置中不再使用 LoggerFactoryResolver
GFramework.Core.Tests/ecs/EcsBasicTests.cs
GFramework.Core.Tests/ecs/EcsIntegrationTests.cs
GFramework.Core.Tests/ecs/EcsAdvancedTests.cs
删除与旧实现绑定的过时 ECS 抽象和模块。
  • 从 abstractions 项目中删除 IEcsWorldIEcsSystem 抽象。
  • 从 core 项目中删除 EcsWorldEcsSystemBaseEcsSystemRunner 以及旧的 EcsModule 实现。
  • 通过仅依赖新的基于 Arch 的 ECS 集成,隐式更新项目引用。
GFramework.Core.Abstractions/ecs/IEcsWorld.cs
GFramework.Core.Abstractions/ecs/IEcsSystem.cs
GFramework.Core/ecs/EcsWorld.cs
GFramework.Core/ecs/EcsSystemBase.cs
GFramework.Core/ecs/EcsSystemRunner.cs
GFramework.Core/services/modules/EcsModule.cs

技巧和命令(Tips and commands)

与 Sourcery 交互(Interacting with Sourcery)

  • 触发新的审查: 在 pull request 中评论 @sourcery-ai review
  • 继续讨论: 直接回复 Sourcery 的审查评论。
  • 从审查评论生成 GitHub issue: 在审查评论下回复,请求 Sourcery 基于该评论创建一个 issue。你也可以在审查评论下回复 @sourcery-ai issue 来从该评论创建 issue。
  • 生成 pull request 标题: 在 pull request 标题中任意位置写上 @sourcery-ai,即可随时生成标题。你也可以在 pull request 中评论 @sourcery-ai title 来(重新)生成标题。
  • 生成 pull request 摘要: 在 pull request 正文任意位置写上 @sourcery-ai summary,即可在该位置生成 PR 摘要。你也可以在 pull request 中评论 @sourcery-ai summary 来(重新)生成摘要。
  • 生成审查者指南: 在 pull request 中评论 @sourcery-ai guide,即可随时(重新)生成审查者指南。
  • 一键解决所有 Sourcery 评论: 在 pull request 中评论 @sourcery-ai resolve,即可将所有 Sourcery 评论标记为已解决。如果你已经处理完所有评论且不希望再看到它们,这会很有用。
  • 关闭所有 Sourcery 审查: 在 pull request 中评论 @sourcery-ai dismiss,即可关闭所有现有的 Sourcery 审查。特别适用于想要从一次全新的审查开始的场景——别忘了再评论 @sourcery-ai review 来触发新的审查!

自定义你的体验(Customizing Your Experience)

访问你的 控制面板(dashboard) 以:

  • 启用或禁用审查特性,例如 Sourcery 生成的 pull request 摘要、审查者指南等。
  • 更改审查语言。
  • 添加、删除或编辑自定义审查指令。
  • 调整其他审查设置。

获取帮助(Getting Help)

Original review guide in English

Reviewer's Guide

Refactors the ECS integration from a custom EcsWorld/EcsSystem* abstraction to an Arch.Core-based ArchEcsModule and ArchSystemAdapter, updating tests and service wiring to use the new architecture adapter and removing old ECS APIs from the architecture context.

Sequence diagram for ECS update using ArchEcsModule and ArchSystemAdapter

sequenceDiagram
    participant GL as GameLoop
    participant AEM as ArchEcsModule
    participant SYS as MovementSystem
    participant W as World

    GL->>AEM: Update(deltaTime)
    loop for each ArchSystemAdapter<float>
        AEM->>SYS: Update(deltaTime)
        activate SYS
        SYS->>SYS: OnUpdate(deltaTime)
        SYS->>W: Query(Position, Velocity)
        loop for each matching Entity
            W-->>SYS: ref Position, ref Velocity
            SYS->>SYS: pos.X += vel.X * deltaTime
            SYS->>SYS: pos.Y += vel.Y * deltaTime
        end
        deactivate SYS
    end
Loading

Class diagram for new Arch-based ECS integration

classDiagram
    direction LR

    class IServiceModule {
        <<interface>>
        +string ModuleName
        +int Priority
        +bool IsEnabled
        +void Register(IIocContainer container)
        +void Initialize()
        +ValueTask DestroyAsync()
    }

    class IIocContainer {
        <<interface>>
        +void Register(object instance)
        +T Get~T~()
        +List~T~ GetAll~T~()
    }

    class World {
        +static World Create()
        +static void Destroy(World world)
        +int Size
        +Entity Create()
        +Entity Create(Position position, Velocity velocity)
        +void Destroy(Entity entity)
        +void Clear()
        +bool IsAlive(Entity entity)
        +bool Has~T~(Entity entity)
        +ref T Get~T~(Entity entity)
        +void Add~T~(Entity entity, T component)
        +void Remove~T~(Entity entity)
    }

    class AbstractSystem {
        <<abstract>>
        +void Initialize()
        +void Destroy()
        #void OnInit()
        #void OnDestroy()
    }

    namespace Arch_System {
        class ISystem_T_ {
            <<interface>>
            +void Initialize()
            +void BeforeUpdate(T t)
            +void Update(T t)
            +void AfterUpdate(T t)
        }
    }

    class ArchSystemAdapter_T_ {
        <<abstract>>
        +World World
        +void Initialize()
        +void Destroy()
        +void Update(T t)
        #void OnInit()
        #void OnDestroy()
        #void OnArchInitialize()
        #void OnBeforeUpdate(T t)
        #void OnUpdate(T t)
        #void OnAfterUpdate(T t)
        #void OnArchDispose()
    }

    class MovementSystem {
        <<sealed>>
        -QueryDescription _query
        #void OnArchInitialize()
        #void OnUpdate(float deltaTime)
    }

    class ArchEcsModule {
        <<sealed>>
        -List~ArchSystemAdapter~float~~ _systems
        -IIocContainer _container
        -World _world
        +string ModuleName
        +int Priority
        +bool IsEnabled
        +ArchEcsModule(bool enabled)
        +void Register(IIocContainer container)
        +void Initialize()
        +ValueTask DestroyAsync()
        +void Update(float deltaTime)
    }

    class ServiceModuleManager {
        -ILogger _logger
        +void RegisterBuiltInModules(IIocContainer container, ArchitectureProperties properties)
    }

    class Position {
        <<struct>>
        +float X
        +float Y
    }

    class Velocity {
        <<struct>>
        +float X
        +float Y
    }

    IServiceModule <|.. ArchEcsModule
    AbstractSystem <|-- ArchSystemAdapter_T_
    Arch_System.ISystem_T_ <|.. ArchSystemAdapter_T_

    ArchSystemAdapter_T_ --> World : uses

    ArchSystemAdapter_float_ <|-- MovementSystem

    ArchEcsModule o-- World : owns
    ArchEcsModule o-- "*" ArchSystemAdapter_float_ : manages

    ServiceModuleManager --> ArchEcsModule : registers
    ServiceModuleManager --> IIocContainer : uses

    World --> Position : component
    World --> Velocity : component
Loading

File-Level Changes

Change Details Files
Replace custom ECS world/system implementation with Arch.Core-based adapter layer and module.
  • Introduce ArchSystemAdapter that bridges Arch.System.ISystem with the framework AbstractSystem lifecycle and exposes Arch.Core.World via DI.
  • Add ArchEcsModule that owns an Arch.Core.World, resolves all ArchSystemAdapter systems from the container, manages their initialization, update, and async destruction, and registers the world as a service.
  • Update ServiceModuleManager to register ArchEcsModule instead of the old EcsModule when ECS is enabled in configuration.
GFramework.Core/ecs/ArchSystemAdapter.cs
GFramework.Core/ecs/ArchEcsModule.cs
GFramework.Core/services/ServiceModuleManager.cs
Adapt the MovementSystem to the new ArchSystemAdapter and Arch.Core world usage.
  • Change MovementSystem to inherit from ArchSystemAdapter instead of EcsSystemBase.
  • Move initialization logic into OnArchInitialize and update logic into OnUpdate, querying Arch.Core.World directly using QueryDescription.
  • Remove Priority and EcsSystemBase-specific lifecycle, simplifying the system to pure Arch behavior wrapped by the adapter.
GFramework.Core/ecs/systems/MovementSystem.cs
Update ECS components to be Arch-friendly value types.
  • Annotate Position and Velocity structs with StructLayout(LayoutKind.Sequential) to ensure predictable layout for Arch ECS.
  • Slightly adjust XML documentation comments to describe their use in the new ECS context.
GFramework.Core/ecs/components/Position.cs
GFramework.Core/ecs/components/Velocity.cs
Remove ECS-specific APIs from the architecture context abstraction and its test doubles.
  • Delete GetEcsWorld and RegisterEcsSystem from IArchitectureContext and ArchitectureContext, reflecting that ECS is now driven by ArchEcsModule instead of the context.
  • Remove ECS methods from test implementations of IArchitectureContext used in ArchitectureServicesTests and GameContextTests.
GFramework.Core.Abstractions/architecture/IArchitectureContext.cs
GFramework.Core/architecture/ArchitectureContext.cs
GFramework.Core.Tests/architecture/ArchitectureServicesTests.cs
GFramework.Core.Tests/architecture/GameContextTests.cs
Rewrite ECS tests to target Arch.Core World and ArchEcsModule instead of the old EcsWorld/EcsSystemRunner APIs.
  • Refactor basic, integration, and advanced ECS tests to create and use MicrosoftDiContainer + ArchitectureContext, initialize ArchEcsModule, and resolve Arch.Core.World from the container.
  • Change world/entity assertions from EcsWorld.EntityCount/IsAlive/InternalWorld to Arch.Core.World.Size/IsAlive and direct component access on World.
  • Replace system-runner-based execution (EcsSystemRunner, IEcsSystem lists, priorities) with ArchEcsModule.Update and direct registration of MovementSystem as an ArchSystemAdapter in the container.
  • Adjust or remove tests that validated old APIs (EcsWorld idempotent dispose, priority ordering, GetEcsWorld, EcsSystemRunner behavior), adding new tests for ArchEcsModule lifecycle (destroy async, no-systems behavior, accumulated updates, multiple-entity scenarios).
  • Drop logging-related setup in tests since the new flow no longer uses LoggerFactoryResolver in the ECS setup.
GFramework.Core.Tests/ecs/EcsBasicTests.cs
GFramework.Core.Tests/ecs/EcsIntegrationTests.cs
GFramework.Core.Tests/ecs/EcsAdvancedTests.cs
Remove obsolete ECS abstractions and modules tied to the old implementation.
  • Delete IEcsWorld and IEcsSystem abstractions from the abstractions project.
  • Delete EcsWorld, EcsSystemBase, EcsSystemRunner, and the old EcsModule implementation from the core project.
  • Update project references implicitly by relying solely on the new Arch-based ECS integration.
GFramework.Core.Abstractions/ecs/IEcsWorld.cs
GFramework.Core.Abstractions/ecs/IEcsSystem.cs
GFramework.Core/ecs/EcsWorld.cs
GFramework.Core/ecs/EcsSystemBase.cs
GFramework.Core/ecs/EcsSystemRunner.cs
GFramework.Core/services/modules/EcsModule.cs

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@deepsource-io

deepsource-io Bot commented Mar 1, 2026

Copy link
Copy Markdown

DeepSource Code Review

We reviewed changes in f98c7f1...6d36081 on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

Important

Some issues found as part of this review are outside of the diff in this pull request and aren't shown in the inline review comments due to GitHub's API limitations. You can see those issues on the DeepSource dashboard.

PR Report Card

Overall Grade  

Focus Area: Reliability
Security  

Reliability  

Complexity  

Hygiene  

Code Review Summary

Analyzer Status Updated (UTC) Details
C# Mar 2, 2026 1:20p.m. Review ↗
Secrets Mar 2, 2026 1:20p.m. Review ↗

Comment thread GFramework.Core.Tests/ecs/EcsAdvancedTests.cs Outdated

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

你好,我发现了两个问题,并给出了一些整体性的反馈:

  • 在 ArchSystemAdapter 中,OnUpdate 的 XML 注释说明它是抽象方法,但该方法实际上是带有默认空实现的 virtual;建议要么将其改为 abstract,以强制在派生系统中重写,要么更新注释以反映当前的行为。
  • ArchEcsModule.Initialize() 在每次调用时都会向 _systems 追加内容;如果 Initialize 在应用程序生命周期中可能被调用多次,那么最好增加防重初始化的保护(例如在重新初始化前清空 _systems,或者增加一个已初始化的标记)。
给 AI 代理的提示
请根据本次代码评审中的评论进行修改:

## 总体说明
- 在 ArchSystemAdapter<T> 中,OnUpdate 的 XML 注释说明它是抽象方法,但该方法实际上是带有默认空实现的 virtual;建议要么将其改为 abstract,以强制在派生系统中重写,要么更新注释以反映当前的行为。
- ArchEcsModule.Initialize() 在每次调用时都会向 _systems 追加内容;如果 Initialize 在应用程序生命周期中可能被调用多次,那么最好增加防重初始化的保护(例如在重新初始化前清空 _systems,或者增加一个已初始化的标记)。

## 具体评论

### Comment 1
<location path="GFramework.Core/ecs/ArchSystemAdapter.cs" line_range="8-17" />
<code_context>
-
-    // === ECS 支持 ===
-
-    /// <summary>
-    ///     获取ECS世界实例
-    /// </summary>
</code_context>
<issue_to_address>
**suggestion:** XML 注释将 OnUpdate 描述为抽象方法,但该方法实际上是一个带有默认空实现的 virtual 方法。

注释中使用了“受保护抽象方法”和“子类必须重写此方法”的表述,但 `OnUpdate` 实际上是 `protected virtual` 且方法体为空。建议要么将其改为 `abstract`,以强制子类必须重写;要么更新注释,说明重写是可选的,并且默认实现不执行任何操作。

建议实现如下:

```csharp
    /// <summary>
    ///     受保护虚方法,在系统更新时被调用。
    ///     默认实现不执行任何操作,子类可以根据需要选择性地重写此方法以实现具体的系统逻辑。
    /// </summary>

```

如果该文件(或相关基类)中还有其他 XML 注释仍然将 `OnUpdate` 描述为“抽象”或说明子类“必须重写此方法”,也应当一并更新,以反映 `OnUpdate` 实际上是一个 `protected virtual` 方法,重写是可选的,且默认实现为空操作。
</issue_to_address>

### Comment 2
<location path="GFramework.Core/ecs/ArchEcsModule.cs" line_range="75-99" />
<code_context>
+    /// <summary>
+    ///     异步销毁
+    /// </summary>
+    public async ValueTask DestroyAsync()
+    {
+        if (!IsEnabled) return;
+
+        // 销毁所有系统
+        foreach (var system in _systems)
+        {
+            system.Destroy();
+        }
+
+        _systems.Clear();
+
+        // 销毁 World
+        if (_world != null)
+        {
+            World.Destroy(_world);
+            _world = null;
+        }
+
+        await ValueTask.CompletedTask;
+    }
+
</code_context>
<issue_to_address>
**suggestion:** DestroyAsync 被标记为 async,但内部只执行同步工作并等待一个已完成的任务。

由于这里的所有工作都是同步的,并且最后只是执行 `await ValueTask.CompletedTask;``async` 状态机会带来额外开销而没有实际收益。可以考虑将该方法改为非 async,在清理完成后直接返回 `ValueTask.CompletedTask`;或者只有在未来预期会有真正的异步操作时才保留 async 签名。

```suggestion
    /// <summary>
    ///     异步销毁
    /// </summary>
+    public ValueTask DestroyAsync()
+    {
+        if (!IsEnabled) return ValueTask.CompletedTask;
+
+        // 销毁所有系统
+        foreach (var system in _systems)
+        {
+            system.Destroy();
+        }
+
+        _systems.Clear();
+
+        // 销毁 World
+        if (_world != null)
+        {
+            World.Destroy(_world);
+            _world = null;
+        }
+
+        return ValueTask.CompletedTask;
+    }
+
```
</issue_to_address>

Sourcery 对开源项目免费使用——如果你觉得我们的评审有帮助,欢迎分享 ✨
帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈进一步改进评审质量。
Original comment in English

Hey - I've found 2 issues, and left some high level feedback:

  • In ArchSystemAdapter, the XML comment for OnUpdate says it is abstract but the method is virtual with a default empty implementation; either make it abstract to enforce overriding in derived systems or adjust the comment to reflect the current behavior.
  • ArchEcsModule.Initialize() will append to _systems each time it is called; if Initialize can be invoked more than once in the application lifecycle it would be safer to guard against double-initialization (e.g., by clearing _systems or tracking an initialized flag).
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In ArchSystemAdapter<T>, the XML comment for OnUpdate says it is abstract but the method is virtual with a default empty implementation; either make it abstract to enforce overriding in derived systems or adjust the comment to reflect the current behavior.
- ArchEcsModule.Initialize() will append to _systems each time it is called; if Initialize can be invoked more than once in the application lifecycle it would be safer to guard against double-initialization (e.g., by clearing _systems or tracking an initialized flag).

## Individual Comments

### Comment 1
<location path="GFramework.Core/ecs/ArchSystemAdapter.cs" line_range="8-17" />
<code_context>
-
-    // === ECS 支持 ===
-
-    /// <summary>
-    ///     获取ECS世界实例
-    /// </summary>
</code_context>
<issue_to_address>
**suggestion:** The XML comment describes OnUpdate as abstract, but the method is virtual with a default empty implementation.

The summary says "受保护抽象方法" and "子类必须重写此方法", but `OnUpdate` is `protected virtual` with a no-op body. Either change it to `abstract` to enforce overriding, or update the comment to indicate that overriding is optional and the default implementation does nothing.

Suggested implementation:

```csharp
    /// <summary>
    ///     受保护虚方法,在系统更新时被调用。
    ///     默认实现不执行任何操作,子类可以根据需要选择性地重写此方法以实现具体的系统逻辑。
    /// </summary>

```

If there are other XML comments in this file (or related base classes) that still describe `OnUpdate` as “抽象” or state that subclasses “必须重写此方法”, they should be updated similarly to reflect that `OnUpdate` is a `protected virtual` method with an optional override and a no-op default implementation.
</issue_to_address>

### Comment 2
<location path="GFramework.Core/ecs/ArchEcsModule.cs" line_range="75-99" />
<code_context>
+    /// <summary>
+    ///     异步销毁
+    /// </summary>
+    public async ValueTask DestroyAsync()
+    {
+        if (!IsEnabled) return;
+
+        // 销毁所有系统
+        foreach (var system in _systems)
+        {
+            system.Destroy();
+        }
+
+        _systems.Clear();
+
+        // 销毁 World
+        if (_world != null)
+        {
+            World.Destroy(_world);
+            _world = null;
+        }
+
+        await ValueTask.CompletedTask;
+    }
+
</code_context>
<issue_to_address>
**suggestion:** DestroyAsync is marked async but only performs synchronous work and awaits a completed task.

Since all work here is synchronous and you end with `await ValueTask.CompletedTask;`, the `async` state machine adds overhead without value. Consider either making this method non-async and returning `ValueTask.CompletedTask` directly after the cleanup, or keeping an async signature only if you expect real async operations later.

```suggestion
    /// <summary>
    ///     异步销毁
    /// </summary>
+    public ValueTask DestroyAsync()
+    {
+        if (!IsEnabled) return ValueTask.CompletedTask;
+
+        // 销毁所有系统
+        foreach (var system in _systems)
+        {
+            system.Destroy();
+        }
+
+        _systems.Clear();
+
+        // 销毁 World
+        if (_world != null)
+        {
+            World.Destroy(_world);
+            _world = null;
+        }
+
+        return ValueTask.CompletedTask;
+    }
+
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread GFramework.Core/ecs/ArchSystemAdapter.cs
Comment thread GFramework.Core/ecs/ArchEcsModule.cs
- 添加 _isInitialized 标志防止 ArchEcsModule 重复初始化
- 在 Initialize 方法中检查是否已初始化避免重复执行
- 设置初始化标志在所有系统初始化完成后
- 修改 DestroyAsync 方法确保仅在已初始化时执行销毁
- 重置 _isInitialized 标志为 false 在销毁时
- 修正 ArchSystemAdapter 注释描述 OnUpdate 为虚方法而非抽象方法
- 简化 EcsAdvancedTests 中的断言语法移除不必要的大括号
Comment thread GFramework.Core.Tests/ecs/EcsAdvancedTests.cs
GeWuYou added 2 commits March 2, 2026 21:15
- 移除 DestroyAsync 方法中的 async 关键字
- 修改条件判断逻辑,确保返回正确的 ValueTask.CompletedTask
- 删除不必要的 await 关键字,直接返回 ValueTask.CompletedTask
- 保持方法的异步操作正确性
- 修改了核心更新逻辑方法的文档描述
- 明确说明该方法为受保护虚方法,默认不执行任何操作
- 详细说明子类可以按需选择性重写此方法来实现具体系统逻辑
- 更新了参数说明文档
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant