Conversation
- 收敛 GameContext 为单活动上下文模型并保留类型别名兼容查找 - 统一 MicrosoftDiContainer 预冻结实例读取路径并补充 CQRS 注册阶段提示 - 更新 Core 测试、上下文文档与 ai-plan 追踪记录
- 修复 Architecture 销毁后 GameContext 仍保留活动上下文的问题 - 补充生命周期回归测试并验证失败初始化后的解绑路径 - 收口生成器文档中的多架构表述并更新 ai-plan 追踪
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (8)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (4)
📜 Recent review details⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
🧰 Additional context used📓 Path-based instructions (8)**/*.cs📄 CodeRabbit inference engine (CLAUDE.md)
Files:
**/*[!.]*📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.{cs,ts,tsx,js,jsx,py,sh}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.{cs,ts,tsx,js,jsx,py}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.{csproj,cs}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.{cs,ts,tsx,js,jsx,py,sh,xml,csproj,props,targets}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.{cs,ts,tsx,js,jsx,py,sh,xml}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.{md,mdx}📄 CodeRabbit inference engine (AGENTS.md)
Files:
🧠 Learnings (1)📚 Learning: 2026-04-06T12:45:43.921ZApplied to files:
🪛 LanguageToolai-plan/public/single-context-priority/todos/single-context-priority-tracking.md[uncategorized] ~20-~20: 您的意思是“"不"齐”? (BU) 🔇 Additional comments (2)
📝 WalkthroughWalkthrough本 PR 将 GameContext 从多上下文字典改为单一“当前活动上下文”模型,调整 MicrosoftDiContainer 在预冻结阶段的实例可见性与去重逻辑,并确保 Architecture.DestroyAsync 在销毁时始终从全局注册表解绑上下文;同时补充相关测试与文档说明。(约 34 字) Changes单一活动上下文语义重构及生命周期清理
Sequence Diagram(s)sequenceDiagram
participant Architecture
participant GameContext
participant ContextAwareProbe
Architecture->>GameContext: Bind(architectureType, context)
GameContext-->>Architecture: record _currentArchitectureContext
ContextAwareProbe->>GameContext: GetFirstArchitectureContext()/TryGet -> 返回活动上下文
Architecture->>Architecture: DestroyAsync()
Architecture->>GameContext: Unbind(GetType()) (in finally)
GameContext-->>ContextAwareProbe: subsequent GetContext() 抛出/不可用
sequenceDiagram
participant Registrar
participant MicrosoftDiContainer
participant ServiceProvider
Registrar->>MicrosoftDiContainer: RegisterSingleton / RegisterPlurality / RegisterCqrsHandlers...
MicrosoftDiContainer->>MicrosoftDiContainer: CollectRegisteredImplementationInstances (pre-freeze)
MicrosoftDiContainer-->>Registrar: Get<T>() 返回收集并去重后的实例
Registrar->>MicrosoftDiContainer: Freeze() -> 构建 _provider
MicrosoftDiContainer->>ServiceProvider: Get<T>() (post-freeze) 使用内建 provider 解析
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary
Test ResultsDetails
Insights
build-and-test: Run #1072
🎉 All tests passed!Slowest Tests
🎉 No failed tests in this run. | 🍂 No flaky tests in this run. Github Test Reporter by CTRF 💚 |
✅
|
| Descriptor | Linter | Files | Fixed | Errors | Warnings | Elapsed time |
|---|---|---|---|---|---|---|
| dotnet-format | yes | 1 | no | 5.66s | ||
| ✅ REPOSITORY | gitleaks | yes | no | no | 8.38s | |
| ✅ REPOSITORY | trufflehog | yes | no | no | 7.04s |
Detailed Issues
⚠️ CSHARP / dotnet-format - 1 error
Welcome to .NET 9.0!
---------------------
SDK Version: 9.0.114
----------------
Installed an ASP.NET Core HTTPS development certificate.
To trust the certificate, run 'dotnet dev-certs https --trust'
Learn about HTTPS: https://aka.ms/dotnet-https
----------------
Write your first app: https://aka.ms/dotnet-hello-world
Find out what's new: https://aka.ms/dotnet-whats-new
Explore documentation: https://aka.ms/dotnet-docs
Report issues and find source on GitHub: https://github.com/dotnet/core
Use 'dotnet --help' to see available commands or visit: https://aka.ms/dotnet-cli
--------------------------------------------------------------------------------------
Unhandled exception: System.Exception: Restore operation failed.
at Microsoft.CodeAnalysis.Tools.CodeFormatter.OpenMSBuildWorkspaceAsync(String solutionOrProjectPath, WorkspaceType workspaceType, Boolean noRestore, Boolean requiresSemantics, String binaryLogPath, Boolean logWorkspaceWarnings, ILogger logger, CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.Tools.CodeFormatter.FormatWorkspaceAsync(FormatOptions formatOptions, ILogger logger, CancellationToken cancellationToken, String binaryLogPath)
at Microsoft.CodeAnalysis.Tools.FormatCommandCommon.FormatAsync(FormatOptions formatOptions, ILogger`1 logger, CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.Tools.Commands.RootFormatCommand.FormatCommandDefaultHandler.InvokeAsync(ParseResult parseResult, CancellationToken cancellationToken)
at System.CommandLine.Invocation.InvocationPipeline.InvokeAsync(ParseResult parseResult, CancellationToken cancellationToken)
See detailed reports in MegaLinter artifacts
Set VALIDATE_ALL_CODEBASE: true in mega-linter.yml to validate all sources, not only the diff

Show us your support by starring ⭐ the repository
|
| Filename | Overview |
|---|---|
| GFramework.Core/Architectures/GameContext.cs | Core refactor: replaces Interlocked/ConcurrentDictionary-only approach with unified SyncRoot lock. All state transitions are now atomic; the ConcurrentDictionary is retained solely to provide a lock-free live view via ArchitectureReadOnlyDictionary. |
| GFramework.Core/Architectures/Architecture.cs | Destroy() now mirrors DestroyAsync() with a finally-guarded Unbind; both paths correctly clean up the GameContext binding even if the lifecycle layer throws. |
| GFramework.Core/Rule/ContextAwareBase.cs | Documentation-only change; the documented stale-reference risk after architecture destruction is accurate and worth preserving for callers. |
| GFramework.Core/Ioc/MicrosoftDiContainer.cs | Pre-freeze Get/Get(Type) and ResolveCqrsRegistrationService now share CollectRegisteredImplementationInstances, making instance visibility consistent across all pre-freeze query paths. |
| GFramework.Core.Tests/Architectures/ArchitectureLifecycleBehaviorTests.cs | New regression tests cover: destroy unbind, failed-init destroy unbind, post-destroy ContextAware fallback, and synchronous Destroy() unbind. SetUp/TearDown correctly use GameContext.Clear(). |
| GFramework.Core.Tests/Architectures/GameContextTests.cs | Tests updated to reflect the new single-context semantics; new cases cover different-instance rejection, alias-aware unbind retention, and context-type fallback resolution. |
| GFramework.Core.Tests/Rule/ContextAwareTests.cs | GetContext fallback test strengthened from DoesNotThrow to asserting the actual returned instance. TearDown uses Unbind rather than Clear(); correct today but fragile if the fixture grows. |
| GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs | New tests document pre-freeze visibility contract: RegisterPlurality aliases are visible, implementation-type registrations are not, and CQRS handler registration is verified end-to-end. |
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 2
GFramework.Core.Tests/Rule/ContextAwareTests.cs:35-39
The TearDown calls `Unbind(typeof(TestArchitectureContext))` rather than `Clear()`. This works correctly for the current fixture (SetUp adds exactly one binding), but is fragile: if any future test in this fixture adds a second alias, the cleanup is incomplete. All other test fixtures that touch `GameContext` use `Clear()` in their teardown for this exact reason.
```suggestion
[TearDown]
public void TearDown()
{
GameContext.Clear();
}
```
### Issue 2 of 2
GFramework.Core/Architectures/GameContext.cs:21-23
**Redundant internal locking in `ConcurrentDictionary`**
All mutations to `ArchitectureDictionary` already happen exclusively inside `lock (SyncRoot)`, so `ConcurrentDictionary`'s internal per-bucket locks are never needed for writes. The only callers that benefit from `ConcurrentDictionary`'s thread-safety are external readers of `ArchitectureReadOnlyDictionary`, which see a live snapshot without holding `SyncRoot`. That use-case is valid and documented in the comment above, but worth keeping in mind if lock contention becomes a concern.
Reviews (2): Last reviewed commit: "fix(core): 修复上下文销毁解绑与并发一致性" | Re-trigger Greptile
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
GFramework.Core/Architectures/Architecture.cs (1)
379-383:⚠️ Potential issue | 🟠 Major | ⚡ Quick win
Destroy()(同步已废弃方法)未调用GameContext.Unbind(),可能遗留全局过期绑定
DestroyAsync()在finally中执行GameContext.Unbind(GetType()),确保销毁后全局回退路径失效。但同步的Destroy()仅调用_lifecycle.Destroy(),不执行任何解绑。若调用方仍使用
Destroy()(尽管已标记[Obsolete]),架构生命周期组件会被清理,但GameContext仍持有该架构实例的过期引用。后续任何ContextAwareBase.GetContext()的惰性调用都会命中这个已销毁的上下文,导致难以排查的运行时错误。🔧 建议修复
[Obsolete("建议使用 DestroyAsync() 以支持异步清理")] public virtual void Destroy() { - _lifecycle.Destroy(); + try + { + _lifecycle.Destroy(); + } + finally + { + // 与 DestroyAsync 保持一致:销毁后必须解除全局回退入口 + GameContext.Unbind(GetType()); + } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Core/Architectures/Architecture.cs` around lines 379 - 383, The synchronous Destroy() currently only calls _lifecycle.Destroy() and omits the GameContext.Unbind(GetType()) cleanup performed by DestroyAsync(), leaving stale global bindings; update Destroy() (the obsolete synchronous method) to perform the same unbind logic as DestroyAsync() — ensure GameContext.Unbind(GetType()) is invoked (ideally in a finally-equivalent block around _lifecycle.Destroy()) so ContextAwareBase.GetContext() cannot later return a destroyed instance.
🧹 Nitpick comments (5)
GFramework.Core/Architectures/GameContextProvider.cs (1)
14-21: ⚡ Quick win
GetContext()缺少<exception>XML 文档标注
GetContext()调用GameContext.GetFirstArchitectureContext(),在无活动上下文时会抛出InvalidOperationException(对应ContextProviderTests.cs中的GameContextProvider_GetContext_Should_Throw_When_Empty测试)。按编码规范,方法可能抛出的异常必须通过<exception>标签声明。📝 建议补充的 XML 文档
/// <summary> /// 获取当前的架构上下文。 /// </summary> /// <returns>架构上下文实例</returns> + /// <exception cref="InvalidOperationException">当前没有已绑定的活动架构上下文时抛出。</exception> public IArchitectureContext GetContext()As per coding guidelines: "XML documentation MUST use
<summary>,<param>,<returns>,<exception>, and<remarks>where applicable."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Core/Architectures/GameContextProvider.cs` around lines 14 - 21, The GetContext() XML docs must declare the possible InvalidOperationException thrown by GameContext.GetFirstArchitectureContext(); update the method's XML documentation to include an <exception> tag describing that InvalidOperationException is thrown when there is no active architecture context (as covered by ContextProviderTests.cs::GameContextProvider_GetContext_Should_Throw_When_Empty), while keeping the existing <summary> and <returns> intact.GFramework.Core/Rule/ContextAwareBase.cs (1)
48-56: ⚡ Quick win建议在
<remarks>中补充一次性缓存的生命周期警告当
GetContext()通过回退路径拿到上下文并写入Context字段后,后续即使架构调用DestroyAsync()触发GameContext.Unbind(),该实例的Context缓存也不会被清除,仍然指向已销毁的上下文。这一行为对调用方有隐含的生命周期假设,按编码规范应在 XML 文档中显式说明。📝 建议补充的 `` 内容
/// <remarks> /// 当 <see cref="Context" /> 为空时,该实现会直接回退到 <see cref="GameContext.GetFirstArchitectureContext" /> 返回的当前活动上下文。 /// 该回退过程不执行额外同步,也不支持替换 provider;如需这些能力,请改用生成的 ContextAware 实现。 + /// 回退结果会被缓存到 <see cref="Context" />;一旦缓存,即使关联架构随后调用 <see cref="GameContext" />.Unbind 解除绑定, + /// 该实例仍将持有原上下文引用,不会自动置空。 /// </remarks>As per coding guidelines: "If a C# member participates in lifecycle, threading, registration, or disposal behavior, document that behavior explicitly."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Core/Rule/ContextAwareBase.cs` around lines 48 - 56, The XML remarks for IContextAware.GetContext() must explicitly document that when the method falls back to GameContext.GetFirstArchitectureContext() and assigns the result to the Context field, that cached Context is one-time and will not be cleared if the architecture later calls DestroyAsync() which triggers GameContext.Unbind(); update the <remarks> to warn callers that Context may continue to reference a destroyed context, describe the lifecycle implication and threading/registration caveat, and point callers to prefer generated ContextAware implementations if they need automatic cache invalidation or replacement of the provider.GFramework.Core/Architectures/Architecture.cs (1)
359-374: ⚡ Quick win
DestroyAsync()的 XML 文档缺少GameContext.Unbind副作用说明
DestroyAsync()现在在finally中执行全局解绑,这是一个重要的注册/生命周期行为变更,按编码规范必须在 XML 文档中显式说明。📝 建议补充的 XML 文档
/// <summary> /// 异步销毁架构及所有组件 /// </summary> + /// <remarks> + /// 销毁完成后(无论 <see cref="_lifecycle" />.DestroyAsync() 是否抛出),都会调用 + /// <see cref="GameContext.Unbind" /> 解除当前架构类型在全局注册表中的绑定, + /// 确保后续惰性 <c>ContextAwareBase.GetContext()</c> 调用不会命中已销毁的上下文。 + /// </remarks> public virtual async ValueTask DestroyAsync()As per coding guidelines: "If a C# member participates in lifecycle, threading, registration, or disposal behavior, document that behavior explicitly."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Core/Architectures/Architecture.cs` around lines 359 - 374, Update the XML doc for the method DestroyAsync to explicitly call out its side effect: it invokes _lifecycle.DestroyAsync() and then always calls GameContext.Unbind(GetType()) in a finally block to remove the global binding for this architecture type (preventing stale runtime contexts and affecting any ContextAware consumers); mention that this unbind occurs even on exceptions, that the operation is asynchronous (returns ValueTask), and note any threading/lifecycle implications so callers know the global registration is removed during destruction.GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs (1)
489-497: ⚡ Quick win测试断言可加强:仅验证不抛异常,未验证 handler 真的被注册。
Assert.DoesNotThrow能覆盖ResolveCqrsRegistrationService通过实例可见性路径解析成功这一 happy path,但不能区分“注册流程实际执行”与“在解析阶段静默回退”。建议附加一个对GetServicesUnsafe中目标 handler 描述符的存在性断言,复用文件中已有的模式(例如Clear_Should_Reset_Cqrs_Assembly_Deduplication_State)。♻️ 建议补强断言
[Test] public void RegisterCqrsHandlersFromAssemblies_Should_Resolve_Registration_Service_When_Registered_As_Instance() { Assert.DoesNotThrow(() => _container.RegisterCqrsHandlersFromAssemblies([typeof(DeterministicOrderNotification).Assembly])); + + Assert.That( + _container.GetServicesUnsafe.Any(static descriptor => + descriptor.ServiceType == typeof(INotificationHandler<DeterministicOrderNotification>)), + Is.True); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs` around lines 489 - 497, The test RegisterCqrsHandlersFromAssemblies_Should_Resolve_Registration_Service_When_Registered_As_Instance only asserts no exception; update it to also verify the handler descriptor was actually registered by calling GetServicesUnsafe for the CQRS registration service and asserting that a descriptor for DeterministicOrderNotification (or the expected handler type from the assembly) exists; reuse the pattern used in Clear_Should_Reset_Cqrs_Assembly_Deduplication_State to locate the registration via ResolveCqrsRegistrationService and assert the presence (and optionally count) of the handler descriptor rather than relying solely on Assert.DoesNotThrow.GFramework.Core/Architectures/GameContext.cs (1)
90-114: ⚡ Quick winXML 文档未跟随语义变更同步更新。
下列成员的语义在本次重构中已发生变化或与
_currentArchitectureContext的生命周期/线程行为强相关,但 XML 文档没有相应更新:
Get<T>/TryGet<T>:现已优先返回_currentArchitectureContext(如果可分配到T),再退回字典查找。文档仍是泛化的“获取指定类型的架构上下文实例”,未体现新的命中顺序。Unbind:增加了非空校验,并会在“最后一个别名被移除”时清空_currentArchitectureContext;但既缺<exception cref="ArgumentNullException">标注,也未说明对当前活动上下文的副作用。Clear:除清空字典外还会清空_currentArchitectureContext,文档未提及。📝 建议补全的 XML 文档要点
/// <summary> - /// 获取指定类型的架构上下文实例 + /// 获取指定类型的架构上下文实例。 + /// 优先返回当前活动上下文(若可分配到 <typeparamref name="T" />),否则按显式绑定的类型别名在字典中查找。 /// </summary> ... public static T Get<T>() where T : class, IArchitectureContext ... /// <summary> - /// 尝试获取指定类型的架构上下文实例 + /// 尝试获取指定类型的架构上下文实例。 + /// 优先匹配当前活动上下文(若可分配到 <typeparamref name="T" />),否则按显式绑定的类型别名在字典中查找。 /// </summary> ... public static bool TryGet<T>(out T? context) ... /// <summary> - /// 移除指定类型的架构上下文绑定 + /// 移除指定类型的架构上下文绑定。 + /// 若被移除的别名是当前活动上下文的最后一个引用,则同步清空 <c>_currentArchitectureContext</c>; + /// 否则保留当前活动上下文不变。 /// </summary> /// <param name="architectureType">要移除的架构类型</param> + /// <exception cref="ArgumentNullException"><paramref name="architectureType" /> 为 <see langword="null" />。</exception> public static void Unbind(Type architectureType) ... /// <summary> - /// 清空所有架构上下文绑定 + /// 清空所有架构上下文绑定,并同时重置当前活动上下文。 + /// 调用后 <see cref="GetFirstArchitectureContext" /> 将抛出异常,直到再次 <see cref="Bind" />。 /// </summary> public static void Clear()As per coding guidelines: "Any change to public API, lifecycle semantics, module behavior, or extension points MUST update related XML docs in C#" 与 "If a C# member participates in lifecycle, threading, registration, or disposal behavior, document that behavior explicitly"。
Also applies to: 133-159
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@GFramework.Core/Architectures/GameContext.cs` around lines 90 - 114, The XML docs for Get<T>, TryGet<T>, Unbind, and Clear are out-of-date: update their summaries and relevant tags to reflect the new lifecycle and lookup semantics (Get<T>/TryGet<T> now prefer _currentArchitectureContext if assignable to T before falling back to ArchitectureDictionary), document thread/lifecycle side-effects (Unbind now checks for null, removes aliases and clears _currentArchitectureContext when the last alias is removed — add <exception cref="ArgumentNullException"> where appropriate and explain the side effect on the active context), and note that Clear empties both ArchitectureDictionary and _currentArchitectureContext; ensure any threading/ownership/disposal implications are described for these members.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@GFramework.Core/Architectures/GameContext.cs`:
- Around line 137-149: The Unbind/Bind/Clear sequence can suffer a TOCTOU race
between ArchitectureDictionary and _currentArchitectureContext; wrap all
compound operations that modify both the dictionary and the current context
(methods Unbind, Bind, and Clear and any helper that updates
_currentArchitectureContext alongside ArchitectureDictionary) inside a single
private lock (e.g., a dedicated object like _contextLock) so dictionary
removals/additions and the Interlocked/assignment of _currentArchitectureContext
are performed atomically; update GetFirstArchitectureContext (and document
Get<T>/TryGet<T> behavior) to read under the same lock or use a volatile read to
avoid observing a null _currentArchitectureContext when the dictionary still
contains the context.
---
Outside diff comments:
In `@GFramework.Core/Architectures/Architecture.cs`:
- Around line 379-383: The synchronous Destroy() currently only calls
_lifecycle.Destroy() and omits the GameContext.Unbind(GetType()) cleanup
performed by DestroyAsync(), leaving stale global bindings; update Destroy()
(the obsolete synchronous method) to perform the same unbind logic as
DestroyAsync() — ensure GameContext.Unbind(GetType()) is invoked (ideally in a
finally-equivalent block around _lifecycle.Destroy()) so
ContextAwareBase.GetContext() cannot later return a destroyed instance.
---
Nitpick comments:
In `@GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs`:
- Around line 489-497: The test
RegisterCqrsHandlersFromAssemblies_Should_Resolve_Registration_Service_When_Registered_As_Instance
only asserts no exception; update it to also verify the handler descriptor was
actually registered by calling GetServicesUnsafe for the CQRS registration
service and asserting that a descriptor for DeterministicOrderNotification (or
the expected handler type from the assembly) exists; reuse the pattern used in
Clear_Should_Reset_Cqrs_Assembly_Deduplication_State to locate the registration
via ResolveCqrsRegistrationService and assert the presence (and optionally
count) of the handler descriptor rather than relying solely on
Assert.DoesNotThrow.
In `@GFramework.Core/Architectures/Architecture.cs`:
- Around line 359-374: Update the XML doc for the method DestroyAsync to
explicitly call out its side effect: it invokes _lifecycle.DestroyAsync() and
then always calls GameContext.Unbind(GetType()) in a finally block to remove the
global binding for this architecture type (preventing stale runtime contexts and
affecting any ContextAware consumers); mention that this unbind occurs even on
exceptions, that the operation is asynchronous (returns ValueTask), and note any
threading/lifecycle implications so callers know the global registration is
removed during destruction.
In `@GFramework.Core/Architectures/GameContext.cs`:
- Around line 90-114: The XML docs for Get<T>, TryGet<T>, Unbind, and Clear are
out-of-date: update their summaries and relevant tags to reflect the new
lifecycle and lookup semantics (Get<T>/TryGet<T> now prefer
_currentArchitectureContext if assignable to T before falling back to
ArchitectureDictionary), document thread/lifecycle side-effects (Unbind now
checks for null, removes aliases and clears _currentArchitectureContext when the
last alias is removed — add <exception cref="ArgumentNullException"> where
appropriate and explain the side effect on the active context), and note that
Clear empties both ArchitectureDictionary and _currentArchitectureContext;
ensure any threading/ownership/disposal implications are described for these
members.
In `@GFramework.Core/Architectures/GameContextProvider.cs`:
- Around line 14-21: The GetContext() XML docs must declare the possible
InvalidOperationException thrown by GameContext.GetFirstArchitectureContext();
update the method's XML documentation to include an <exception> tag describing
that InvalidOperationException is thrown when there is no active architecture
context (as covered by
ContextProviderTests.cs::GameContextProvider_GetContext_Should_Throw_When_Empty),
while keeping the existing <summary> and <returns> intact.
In `@GFramework.Core/Rule/ContextAwareBase.cs`:
- Around line 48-56: The XML remarks for IContextAware.GetContext() must
explicitly document that when the method falls back to
GameContext.GetFirstArchitectureContext() and assigns the result to the Context
field, that cached Context is one-time and will not be cleared if the
architecture later calls DestroyAsync() which triggers GameContext.Unbind();
update the <remarks> to warn callers that Context may continue to reference a
destroyed context, describe the lifecycle implication and threading/registration
caveat, and point callers to prefer generated ContextAware implementations if
they need automatic cache invalidation or replacement of the provider.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 672e4714-2ac7-4fc6-8daa-1afce38c6c9c
📒 Files selected for processing (18)
GFramework.Core.Abstractions/Ioc/IIocContainer.csGFramework.Core.Tests/Architectures/ArchitectureLifecycleBehaviorTests.csGFramework.Core.Tests/Architectures/ContextProviderTests.csGFramework.Core.Tests/Architectures/GameContextTests.csGFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.csGFramework.Core.Tests/Rule/ContextAwareTests.csGFramework.Core/Architectures/Architecture.csGFramework.Core/Architectures/GameContext.csGFramework.Core/Architectures/GameContextProvider.csGFramework.Core/Ioc/MicrosoftDiContainer.csGFramework.Core/Rule/ContextAwareBase.csai-plan/public/README.mdai-plan/public/single-context-priority/todos/single-context-priority-tracking.mdai-plan/public/single-context-priority/traces/single-context-priority-trace.mddocs/zh-CN/core/context.mddocs/zh-CN/core/rule.mddocs/zh-CN/source-generators/context-aware-generator.mddocs/zh-CN/source-generators/context-get-generator.md
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Build and Test
- GitHub Check: Code Quality & Security
- GitHub Check: Analyze (C#)
🧰 Additional context used
📓 Path-based instructions (10)
**/*.cs
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.cs: Apply [Log] attribute for automatic logging field and logging helper method generation
Apply [Priority] attribute for automatic priority comparison implementation generation
Apply [GenerateEnumExtensions] attribute to generate enumeration extension capabilities
Apply [ContextAware] attribute to automatically implement IContextAware boilerplate logic
**/*.cs: All public, protected, and internal types and members MUST include XML documentation comments (///) in C#
XML documentation MUST use<summary>,<param>,<returns>,<exception>, and<remarks>where applicable, and explain intent, contract, and usage constraints instead of restating syntax
If a C# member participates in lifecycle, threading, registration, or disposal behavior, document that behavior explicitly
Core framework components (Architecture, Module, System, Context, Registry, Service Module, Lifecycle types) MUST include high-level explanations of responsibilities, lifecycle, interaction with other components, why abstraction exists, and when to use instead of alternatives
Generated logic and source generator pipelines MUST explain what is generated, why it is generated, semantic assumptions the generator relies on, and any diagnostics or fallback behavior
Do not rely on implicit imports. Declare every requiredusingexplicitly in C#
Write null-safe code that respects nullable annotations instead of suppressing warnings by default in C#
Use namespace patternGFramework.{Module}.{Feature}with PascalCase segments in C#
Follow standard C# naming: Types/methods/properties/events/constants use PascalCase, Interfaces useIprefix, Parameters and locals use camelCase, Private fields use_camelCase
Use Allman braces style for C#
Keepusingdirectives at the top of the file and sort them consistently in C#
Prefer one primary type per file unless surrounding project already uses different local pattern
Prefer explicit, readable code over clever shorthand in framework internals
M...
Files:
GFramework.Core/Rule/ContextAwareBase.csGFramework.Core.Tests/Rule/ContextAwareTests.csGFramework.Core/Architectures/Architecture.csGFramework.Core/Architectures/GameContextProvider.csGFramework.Core.Tests/Architectures/ContextProviderTests.csGFramework.Core.Tests/Architectures/ArchitectureLifecycleBehaviorTests.csGFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.csGFramework.Core/Ioc/MicrosoftDiContainer.csGFramework.Core.Tests/Architectures/GameContextTests.csGFramework.Core.Abstractions/Ioc/IIocContainer.csGFramework.Core/Architectures/GameContext.cs
**/*[!.]*
📄 CodeRabbit inference engine (AGENTS.md)
For files with shebang lines, keep shebang as first line and place license header immediately after it
Files:
GFramework.Core/Rule/ContextAwareBase.csGFramework.Core.Tests/Rule/ContextAwareTests.csGFramework.Core/Architectures/Architecture.csGFramework.Core/Architectures/GameContextProvider.csai-plan/public/README.mddocs/zh-CN/core/rule.mdai-plan/public/single-context-priority/todos/single-context-priority-tracking.mddocs/zh-CN/source-generators/context-aware-generator.mdGFramework.Core.Tests/Architectures/ContextProviderTests.csdocs/zh-CN/core/context.mddocs/zh-CN/source-generators/context-get-generator.mdGFramework.Core.Tests/Architectures/ArchitectureLifecycleBehaviorTests.csGFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.csai-plan/public/single-context-priority/traces/single-context-priority-trace.mdGFramework.Core/Ioc/MicrosoftDiContainer.csGFramework.Core.Tests/Architectures/GameContextTests.csGFramework.Core.Abstractions/Ioc/IIocContainer.csGFramework.Core/Architectures/GameContext.cs
**/*.{cs,ts,tsx,js,jsx,py,sh}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{cs,ts,tsx,js,jsx,py,sh}: All generated or modified code MUST include clear and meaningful comments where required by documentation rules
Comments MUST NOT be trivial, redundant, or misleading. Prefer explainingwhyandwhen, not justwhat. Code should remain understandable without requiring external context
Avoid obvious comments such as// increment i
Files:
GFramework.Core/Rule/ContextAwareBase.csGFramework.Core.Tests/Rule/ContextAwareTests.csGFramework.Core/Architectures/Architecture.csGFramework.Core/Architectures/GameContextProvider.csGFramework.Core.Tests/Architectures/ContextProviderTests.csGFramework.Core.Tests/Architectures/ArchitectureLifecycleBehaviorTests.csGFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.csGFramework.Core/Ioc/MicrosoftDiContainer.csGFramework.Core.Tests/Architectures/GameContextTests.csGFramework.Core.Abstractions/Ioc/IIocContainer.csGFramework.Core/Architectures/GameContext.cs
**/*.{cs,ts,tsx,js,jsx,py}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{cs,ts,tsx,js,jsx,py}: Add inline comments for non-trivial logic, concurrency/threading behavior, performance-sensitive paths, workarounds/compatibility constraints/edge cases, and registration order/lifecycle sequencing/generated code assumptions
Methods with non-trivial logic MUST document core idea, key decisions, and edge case handling
Separate logical blocks with blank lines when it improves readability
Unless there is clear and documented reason to keep file large, keep single source file under roughly 800-1000 lines
Validate external or user-controlled input before it reaches file system, serialization, reflection, code generation, or process boundaries
Do not build command strings, file paths, type names, or generated code from untrusted input without strict validation or allow-listing
Avoid logging secrets, tokens, credentials, or machine-specific sensitive data
Prefer least-privilege behavior for file, process, and environment access
Files:
GFramework.Core/Rule/ContextAwareBase.csGFramework.Core.Tests/Rule/ContextAwareTests.csGFramework.Core/Architectures/Architecture.csGFramework.Core/Architectures/GameContextProvider.csGFramework.Core.Tests/Architectures/ContextProviderTests.csGFramework.Core.Tests/Architectures/ArchitectureLifecycleBehaviorTests.csGFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.csGFramework.Core/Ioc/MicrosoftDiContainer.csGFramework.Core.Tests/Architectures/GameContextTests.csGFramework.Core.Abstractions/Ioc/IIocContainer.csGFramework.Core/Architectures/GameContext.cs
**/*.{csproj,cs}
📄 CodeRabbit inference engine (AGENTS.md)
Framework runtime, abstractions, and meta-package projects MUST NOT reference
*.SourceGenerators*projects or packages, and MUST NOT use source-generator attributes
Files:
GFramework.Core/Rule/ContextAwareBase.csGFramework.Core.Tests/Rule/ContextAwareTests.csGFramework.Core/Architectures/Architecture.csGFramework.Core/Architectures/GameContextProvider.csGFramework.Core.Tests/Architectures/ContextProviderTests.csGFramework.Core.Tests/Architectures/ArchitectureLifecycleBehaviorTests.csGFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.csGFramework.Core/Ioc/MicrosoftDiContainer.csGFramework.Core.Tests/Architectures/GameContextTests.csGFramework.Core.Abstractions/Ioc/IIocContainer.csGFramework.Core/Architectures/GameContext.cs
**/*.{cs,ts,tsx,js,jsx,py,sh,xml,csproj,props,targets}
📄 CodeRabbit inference engine (AGENTS.md)
Use 4 spaces for indentation. Do not use tabs
Files:
GFramework.Core/Rule/ContextAwareBase.csGFramework.Core.Tests/Rule/ContextAwareTests.csGFramework.Core/Architectures/Architecture.csGFramework.Core/Architectures/GameContextProvider.csGFramework.Core.Tests/Architectures/ContextProviderTests.csGFramework.Core.Tests/Architectures/ArchitectureLifecycleBehaviorTests.csGFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.csGFramework.Core/Ioc/MicrosoftDiContainer.csGFramework.Core.Tests/Architectures/GameContextTests.csGFramework.Core.Abstractions/Ioc/IIocContainer.csGFramework.Core/Architectures/GameContext.cs
**/*.{cs,ts,tsx,js,jsx,py,sh,xml}
📄 CodeRabbit inference engine (AGENTS.md)
Keep line length readable. Around 120 characters is preferred upper bound
Files:
GFramework.Core/Rule/ContextAwareBase.csGFramework.Core.Tests/Rule/ContextAwareTests.csGFramework.Core/Architectures/Architecture.csGFramework.Core/Architectures/GameContextProvider.csGFramework.Core.Tests/Architectures/ContextProviderTests.csGFramework.Core.Tests/Architectures/ArchitectureLifecycleBehaviorTests.csGFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.csGFramework.Core/Ioc/MicrosoftDiContainer.csGFramework.Core.Tests/Architectures/GameContextTests.csGFramework.Core.Abstractions/Ioc/IIocContainer.csGFramework.Core/Architectures/GameContext.cs
**/*.{md,mdx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{md,mdx}: Keep code samples, package names, and command examples aligned with current repository state in documentation
When public page references XML docs or API coverage, convert evidence into reader-facing guidance: explain which types/namespaces/entry points readers should inspect and why
For integration-oriented features such as AI-First config system, documentation MUST cover: project directory layout/file conventions, required project/package wiring, minimal working example, migration/compatibility notes
When examples are rewritten, preserve only parts that remain true. Delete or replace speculative examples instead of lightly editing into another inaccurate form
Files:
ai-plan/public/README.mddocs/zh-CN/core/rule.mdai-plan/public/single-context-priority/todos/single-context-priority-tracking.mddocs/zh-CN/source-generators/context-aware-generator.mddocs/zh-CN/core/context.mddocs/zh-CN/source-generators/context-get-generator.mdai-plan/public/single-context-priority/traces/single-context-priority-trace.md
docs/**/*.md
📄 CodeRabbit inference engine (CLAUDE.md)
Documentation should be organized with Chinese content in docs/zh-CN/ and structured to include getting started, module-specific capabilities (Core, Game, Godot, ECS), source generator usage, tutorials, best practices, and troubleshooting
Files:
docs/zh-CN/core/rule.mddocs/zh-CN/source-generators/context-aware-generator.mddocs/zh-CN/core/context.mddocs/zh-CN/source-generators/context-get-generator.md
**/*Abstractions/**/*.cs
📄 CodeRabbit inference engine (CLAUDE.md)
Abstractions projects should only contain interfaces and contract definitions without any runtime implementation logic
Files:
GFramework.Core.Abstractions/Ioc/IIocContainer.cs
🧠 Learnings (1)
📚 Learning: 2026-04-06T12:45:43.921Z
Learnt from: GeWuYou
Repo: GeWuYou/GFramework PR: 190
File: GFramework.Game/Config/GameConfigBootstrap.cs:1-3
Timestamp: 2026-04-06T12:45:43.921Z
Learning: In the GeWuYou/GFramework repository, C# files may omit explicit `using System*` imports because the project-wide `GlobalUsings.cs` (referenced via manual global `using` directives) supplies common namespaces (e.g., `System`, `System.Threading`, `System.Threading.Tasks`). During code review, do not flag missing `using System...` directives in `.cs` files as long as `GlobalUsings.cs` is present/used to provide those namespaces.
Applied to files:
GFramework.Core/Rule/ContextAwareBase.csGFramework.Core.Tests/Rule/ContextAwareTests.csGFramework.Core/Architectures/Architecture.csGFramework.Core/Architectures/GameContextProvider.csGFramework.Core.Tests/Architectures/ContextProviderTests.csGFramework.Core.Tests/Architectures/ArchitectureLifecycleBehaviorTests.csGFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.csGFramework.Core/Ioc/MicrosoftDiContainer.csGFramework.Core.Tests/Architectures/GameContextTests.csGFramework.Core.Abstractions/Ioc/IIocContainer.csGFramework.Core/Architectures/GameContext.cs
🔇 Additional comments (17)
docs/zh-CN/core/rule.md (1)
93-93: LGTM!新增的"自动回退机制"说明与
ContextAwareBase.cs实现完全对齐。docs/zh-CN/source-generators/context-aware-generator.md (1)
93-105: LGTM!两条路径的回退策略区分说明清晰,与代码实现保持一致。
docs/zh-CN/core/context.md (1)
143-151: LGTM!回退机制的定位和新代码推荐路径表述清晰,与 PR 整体语义对齐。
GFramework.Core.Tests/Architectures/ContextProviderTests.cs (1)
40-79: LGTM!将绑定键从
typeof(TestArchitectureContext)改为typeof(TestArchitecture)正确对齐了Architecture.DestroyAsync()调用GameContext.Unbind(GetType())的语义,并且TryGetContext<TestArchitectureContext>的跨类型兼容性查询也得到了验证。GFramework.Core.Tests/Rule/ContextAwareTests.cs (1)
23-39: 绑定键类型不影响当前活动上下文的设置,测试逻辑正确
GameContext.Bind()的architectureType参数仅作为ArchitectureDictionary的字典键,不控制_currentArchitectureContext的赋值。无论使用typeof(TestArchitectureContext)还是typeof(TestArchitecture)作为绑定键,都会在首次调用Bind时通过Interlocked.CompareExchange将同一context实例设置为当前活动上下文。
GetContext_Should_Return_CurrentArchitectureContext_When_Not_Set测试在SetUp中绑定上下文后,调用GetContext()时正确回退到当前活动上下文并返回_mockContext。本文件使用typeof(TestArchitectureContext)作为键在SetUp和TearDown中一致,测试逻辑完全正确。注:
ContextProviderTests.cs使用typeof(TestArchitecture)作为绑定键,与本文件不同。为了与生产代码中Architecture.DestroyAsync()调用GameContext.Unbind(GetType())的实际行为对齐,建议统一使用typeof(TestArchitecture)作为绑定键。> Likely an incorrect or invalid review comment.ai-plan/public/README.md (1)
45-72: LGTM!新增的
single-context-priority活动主题与 worktree 映射结构与文件其他条目保持一致。GFramework.Core.Abstractions/Ioc/IIocContainer.cs (1)
144-238: LGTM!新增的
<remarks>准确描述了MicrosoftDiContainer在预冻结阶段的实例可见性语义,与实现端CollectRegisteredImplementationInstances的行为一致;<see cref="Freeze" />在同一接口内可正常解析。ai-plan/public/single-context-priority/todos/single-context-priority-tracking.md (1)
1-59: LGTM!跟踪文档结构完整,恢复点、风险、验证记录都清晰呈现。
docs/zh-CN/source-generators/context-get-generator.md (1)
654-705: LGTM!“自定义上下文来源”小节与已有测试/手动装配示例(
SetContextProvider/ResetContextProvider)保持一致,分析器排除场景描述也匹配单活动上下文模型。GFramework.Core.Tests/Architectures/ArchitectureLifecycleBehaviorTests.cs (1)
186-238: LGTM!三个回归测试完整覆盖了
DestroyAsync()解绑全局GameContext的核心契约:成功初始化路径、FailedInitialization路径、以及销毁后新ContextAwareBase实例不再回退到过期上下文。LifecycleContextAwareProbe作为最小探针是合适的设计。ai-plan/public/single-context-priority/traces/single-context-priority-trace.md (1)
1-44: LGTM!时间线追踪覆盖了 RP-001/RP-002 两阶段的实现摘要、验证结果以及 MSBuild copy 冲突的规避说明,便于后续回看。
GFramework.Core/Ioc/MicrosoftDiContainer.cs (3)
600-615: LGTM!
ResolveCqrsRegistrationService复用统一的实例可见性管线后,错误信息也明确指向“注册阶段必须以实例绑定预物化”的契约。LastOrDefault与 MS DI 冻结后GetService<T>()的“最后注册胜出”语义对齐,覆盖RegisterInfrastructure多次接入同一 seam 的场景。
631-674: LGTM!
Get<T>()/Get(Type)的预冻结路径统一走CollectRegisteredImplementationInstances,与GetAll的可见性规则一致;Get(Type)入口处补充了ArgumentNullException.ThrowIfNull(type),防御性合理。
801-889: LGTM!新增的实例收集与去重三件套(
CollectRegisteredImplementationInstances、BuildPreferredVisibleServiceTypes、SelectPreferredVisibleServiceType)逻辑清晰:
- 通过
ReferenceEqualityComparer按实例分组,避免值相等性误判;- 优先保留调用方请求类型,再按“同 ServiceType 注册次数最多”稳定打破并列,正好匹配
GetAll_Should_Preserve_Duplicate_Registrations_For_The_Same_ServiceType_While_Deduplicating_Aliases的预期;- 826-833 行对
ImplementationFactory/ImplementationType的空分支加注释而非删除,能直观表达“预冻结故意不激活”这一契约,与IIocContainer新<remarks>文档前后呼应。XML 文档与 Allman 风格符合仓库规范。
GFramework.Core.Tests/Architectures/GameContextTests.cs (2)
76-238: 测试覆盖与新语义对齐良好。新增/调整的用例覆盖了 “拒绝绑定不同实例”、“按上下文具体类型回查”、“仅按架构类型绑定时
Get<T>仍能命中”、“移除最后一个别名后清空当前上下文”、以及 “保留其他别名时不清空当前上下文” 这几条核心路径,并配合Clear后GetFirstArchitectureContext抛异常的断言形成闭环。
79-89:AnotherTestArchitectureContext类型已在测试项目中正确定义,无需修改。该类型已在
GFramework.Core.Tests/Architectures/AnotherTestArchitectureContext.cs中声明为公开类,继承自TestArchitectureContext,并包含完整的 XML 文档注释。测试代码可以正常编译和运行。GFramework.Core/Architectures/GameContext.cs (1)
39-46: 单实例追踪与回退查找的整体设计清晰。
Bind的非空校验、GetFirstArchitectureContext的语义收敛、GetByType中 “显式别名优先 → 当前活动上下文按类型兼容回退” 的两段式查找、以及Get<T>/TryGet<T>的快路径,逻辑层次分明,错误信息也具备可观察性。除上文指出的并发原子性与文档同步问题外,主体改动方向合理。Also applies to: 59-87, 96-131
- 修复 GameContext 的别名字典与当前活动上下文同步边界,避免解绑与读取路径出现状态漂移 - 修复 Architecture.Destroy() 缺少全局解绑的问题,并补充相关生命周期 XML 文档 - 更新回归测试、CQRS 注册断言与 single-context-priority 跟踪记录
Summary
Test ResultsDetails
Insights
build-and-test: Run #1073
🎉 All tests passed!Slowest Tests
± Comparison with run #1072 at e3209a1 | 🎉 No failed tests detected across all runs. | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 2 runs. Github Test Reporter by CTRF 💚 |
Summary by CodeRabbit
发布说明
新功能
Bug 修复
文档
测试