imp(ioc): add some command line features to scope generator#2612
Merged
LinQingYuu merged 3 commits intodevfrom Mar 16, 2026
Merged
imp(ioc): add some command line features to scope generator#2612LinQingYuu merged 3 commits intodevfrom
LinQingYuu merged 3 commits intodevfrom
Conversation
Reviewer's Guide优化生命周期作用域源生成器以使用新的 IoC/App 命名空间,并扩展命令处理程序生成逻辑,使生成的处理程序可以在命令模型之后可选地接收一个 带可选 isCallback 的生成命令处理程序时序图sequenceDiagram
actor User
participant CliCommandLine as CommandLine
participant StartupService
participant GeneratedScope as GeneratedScopeHandler
participant CommandHandler as UserCommandHandler
User->>CliCommandLine: enter command
CliCommandLine->>StartupService: parsed command text
StartupService->>GeneratedScope: TryHandleCommand(command, handler)
note over StartupService,GeneratedScope: handler signature: (model, isCallback)
StartupService->>GeneratedScope: invoke handler(model, isCallback)
alt HasCommandModelArg and HasIsCallbackArg
GeneratedScope->>CommandHandler: Handle(model, isCallback, otherArgs)
else HasCommandModelArg only
GeneratedScope->>CommandHandler: Handle(model, otherArgs)
else HasIsCallbackArg only
GeneratedScope->>CommandHandler: Handle(isCallback, otherArgs)
else No special args
GeneratedScope->>CommandHandler: Handle(otherArgs)
end
CommandHandler-->>StartupService: completion
更新后依赖注入调用的时序图sequenceDiagram
participant GeneratedScope as GeneratedScopeHandler
participant DependencyGroups
participant Service as InjectedService
GeneratedScope->>DependencyGroups: InvokeInjection(action, identifier, targets)
DependencyGroups->>InjectedService: resolve and invoke action(parameter)
InjectedService-->>DependencyGroups: completion
DependencyGroups-->>GeneratedScope: result
更新后的生命周期作用域生成器模型类图classDiagram
class LifecycleScopeGenerator {
+const string AppNamespace
+const string IocNamespace
+const string ScopeAttributeType
+const string StartMethodAttributeType
+const string StopMethodAttributeType
+const string CommandHandlerMethodAttributeType
+const string DependencyInjectionMethodAttributeType
+void Initialize(IncrementalGeneratorInitializationContext context)
-static void _CollectSources(SourceProductionContext spc, ImmutableArray~ScopeModel~ scopes)
-static string _GenerateScopeSource(ScopeModel model)
-static IEnumerable~string~ _EmitMethod(ScopeMethodModel model)
}
class ScopeModel {
+string Namespace
+string ClassName
+ImmutableArray~ScopeMethodModel~ Methods
}
class ScopeMethodModel {
+string MethodName
+bool Awaitable
}
class StartMethodModel {
}
class StopMethodModel {
}
class CommandHandlerMethodModel {
+string Command
+bool HasCommandModelArg
+bool HasIsCallbackArg
+(string Name, string TypeName, bool HasDefaultValue, object DefaultValue)[] SplitArgs
}
class DependencyInjectionMethodModel {
+string Identifier
+string ParameterType
+int Targets
}
class StartupService {
+static void TryHandleCommand(string command, Action~CommandLine, bool~ handler)
}
class DependencyGroups {
+static void InvokeInjection(Delegate action, string identifier, AttributeTargets targets)
}
ScopeMethodModel <|-- StartMethodModel
ScopeMethodModel <|-- StopMethodModel
ScopeMethodModel <|-- CommandHandlerMethodModel
ScopeMethodModel <|-- DependencyInjectionMethodModel
LifecycleScopeGenerator --> ScopeModel
ScopeModel --> ScopeMethodModel
LifecycleScopeGenerator ..> StartupService : generates calls to
LifecycleScopeGenerator ..> DependencyGroups : generates calls to
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your Experience访问你的 dashboard 以:
Getting HelpOriginal review guide in EnglishReviewer's GuideRefines the lifecycle scope source generator to use new IoC/App namespaces and extends command handler generation so that generated handlers can optionally accept an isCallback boolean along with the command model, while updating dependency injection invocation accordingly. Sequence diagram for generated command handler with optional isCallbacksequenceDiagram
actor User
participant CliCommandLine as CommandLine
participant StartupService
participant GeneratedScope as GeneratedScopeHandler
participant CommandHandler as UserCommandHandler
User->>CliCommandLine: enter command
CliCommandLine->>StartupService: parsed command text
StartupService->>GeneratedScope: TryHandleCommand(command, handler)
note over StartupService,GeneratedScope: handler signature: (model, isCallback)
StartupService->>GeneratedScope: invoke handler(model, isCallback)
alt HasCommandModelArg and HasIsCallbackArg
GeneratedScope->>CommandHandler: Handle(model, isCallback, otherArgs)
else HasCommandModelArg only
GeneratedScope->>CommandHandler: Handle(model, otherArgs)
else HasIsCallbackArg only
GeneratedScope->>CommandHandler: Handle(isCallback, otherArgs)
else No special args
GeneratedScope->>CommandHandler: Handle(otherArgs)
end
CommandHandler-->>StartupService: completion
Sequence diagram for updated dependency injection invocationsequenceDiagram
participant GeneratedScope as GeneratedScopeHandler
participant DependencyGroups
participant Service as InjectedService
GeneratedScope->>DependencyGroups: InvokeInjection(action, identifier, targets)
DependencyGroups->>InjectedService: resolve and invoke action(parameter)
InjectedService-->>DependencyGroups: completion
DependencyGroups-->>GeneratedScope: result
Class diagram for updated lifecycle scope generator modelsclassDiagram
class LifecycleScopeGenerator {
+const string AppNamespace
+const string IocNamespace
+const string ScopeAttributeType
+const string StartMethodAttributeType
+const string StopMethodAttributeType
+const string CommandHandlerMethodAttributeType
+const string DependencyInjectionMethodAttributeType
+void Initialize(IncrementalGeneratorInitializationContext context)
-static void _CollectSources(SourceProductionContext spc, ImmutableArray~ScopeModel~ scopes)
-static string _GenerateScopeSource(ScopeModel model)
-static IEnumerable~string~ _EmitMethod(ScopeMethodModel model)
}
class ScopeModel {
+string Namespace
+string ClassName
+ImmutableArray~ScopeMethodModel~ Methods
}
class ScopeMethodModel {
+string MethodName
+bool Awaitable
}
class StartMethodModel {
}
class StopMethodModel {
}
class CommandHandlerMethodModel {
+string Command
+bool HasCommandModelArg
+bool HasIsCallbackArg
+(string Name, string TypeName, bool HasDefaultValue, object DefaultValue)[] SplitArgs
}
class DependencyInjectionMethodModel {
+string Identifier
+string ParameterType
+int Targets
}
class StartupService {
+static void TryHandleCommand(string command, Action~CommandLine, bool~ handler)
}
class DependencyGroups {
+static void InvokeInjection(Delegate action, string identifier, AttributeTargets targets)
}
ScopeMethodModel <|-- StartMethodModel
ScopeMethodModel <|-- StopMethodModel
ScopeMethodModel <|-- CommandHandlerMethodModel
ScopeMethodModel <|-- DependencyInjectionMethodModel
LifecycleScopeGenerator --> ScopeModel
ScopeModel --> ScopeMethodModel
LifecycleScopeGenerator ..> StartupService : generates calls to
LifecycleScopeGenerator ..> DependencyGroups : generates calls to
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - 我发现了 1 个问题,并给出了一些整体性反馈:
- 在命令处理程序的模型收集逻辑中,当
hasCommandModelArg为 true 时,splitArgs仍然只跳过第一个参数,因此当存在isCallback时,它会被错误地当作SplitArgs的一部分;请调整Skip(...)的逻辑,在同时存在命令模型参数和isCallback时跳过这两个参数。 hasIsCallbackArgIndex的逻辑依赖参数名等于"isCallback";可以考虑将该参数名集中管理(例如提取为常量)或使用nameof,以降低在其它地方修改参数名后出现不匹配的风险。
面向 AI Agent 的提示(Prompt)
Please address the comments from this code review:
## Overall Comments
- In the command handler model collection, `splitArgs` still skips only the first parameter when `hasCommandModelArg` is true, so when `isCallback` is present it will be incorrectly treated as part of `SplitArgs`; adjust the `Skip(...)` logic to skip both the command model and `isCallback` when both are present.
- The `hasIsCallbackArgIndex` logic depends on parameter name equality to `"isCallback"`; consider centralizing the parameter name (e.g., as a constant) or using `nameof` to reduce the chance of mismatches if the parameter name changes elsewhere.
## Individual Comments
### Comment 1
<location path="PCL.Core.SourceGenerators/LifecycleScopeGenerator.cs" line_range="130-132" />
<code_context>
+ var hasIsCallbackArg = paraArray.Length > hasIsCallbackArgIndex
+ && paraArray[hasIsCallbackArgIndex].Type.SpecialType == SpecialType.System_Boolean
+ && paraArray[hasIsCallbackArgIndex].Name == "isCallback";
var splitArgs = (
from para in hasCommandModelArg ? paraArray.Skip(1) : paraArray
let name = para.Name
</code_context>
<issue_to_address>
**issue (bug_risk):** `isCallback` 参数已被检测到,但仍然被包含在 `splitArgs` 中,这很可能会导致生成的处理程序参数错位。
由于 `hasIsCallbackArg` 表示的是一个特殊的框架开关,而不是 CLI 参数,将其包含在 `splitArgs` 中(不管 `hasIsCallbackArg` 是否为 true,都通过 `paraArray.Skip(1)`)会使 `isCallback` 作为第一项 `SplitArgs` 条目暴露出来。这与 `_EmitMethod` 中将 `isCallback` 单独传递的做法不一致。请调整跳过逻辑,使在存在命令模型参数和 `isCallback` 时,两者都被排除在外(例如使用 `Skip(hasCommandModelArg ? (hasIsCallbackArg ? 2 : 1) : (hasIsCallbackArg ? 1 : 0))`),从而确保只有真正的载荷参数出现在 `SplitArgs` 中。
</issue_to_address>帮我变得更有用!请对每条评论点 👍 或 👎,我会根据你的反馈改进后续评审。
Original comment in English
Hey - I've found 1 issue, and left some high level feedback:
- In the command handler model collection,
splitArgsstill skips only the first parameter whenhasCommandModelArgis true, so whenisCallbackis present it will be incorrectly treated as part ofSplitArgs; adjust theSkip(...)logic to skip both the command model andisCallbackwhen both are present. - The
hasIsCallbackArgIndexlogic depends on parameter name equality to"isCallback"; consider centralizing the parameter name (e.g., as a constant) or usingnameofto reduce the chance of mismatches if the parameter name changes elsewhere.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In the command handler model collection, `splitArgs` still skips only the first parameter when `hasCommandModelArg` is true, so when `isCallback` is present it will be incorrectly treated as part of `SplitArgs`; adjust the `Skip(...)` logic to skip both the command model and `isCallback` when both are present.
- The `hasIsCallbackArgIndex` logic depends on parameter name equality to `"isCallback"`; consider centralizing the parameter name (e.g., as a constant) or using `nameof` to reduce the chance of mismatches if the parameter name changes elsewhere.
## Individual Comments
### Comment 1
<location path="PCL.Core.SourceGenerators/LifecycleScopeGenerator.cs" line_range="130-132" />
<code_context>
+ var hasIsCallbackArg = paraArray.Length > hasIsCallbackArgIndex
+ && paraArray[hasIsCallbackArgIndex].Type.SpecialType == SpecialType.System_Boolean
+ && paraArray[hasIsCallbackArgIndex].Name == "isCallback";
var splitArgs = (
from para in hasCommandModelArg ? paraArray.Skip(1) : paraArray
let name = para.Name
</code_context>
<issue_to_address>
**issue (bug_risk):** The `isCallback` parameter is detected but still included in `splitArgs`, which likely misaligns generated handler arguments.
Since `hasIsCallbackArg` indicates a special framework flag rather than a CLI parameter, including it in `splitArgs` (via `paraArray.Skip(1)` regardless of `hasIsCallbackArg`) will expose `isCallback` as the first `SplitArgs` entry. This diverges from `_EmitMethod`, where `isCallback` is passed separately. Adjust the skip logic so both the command model and `isCallback` are excluded when present (e.g., `Skip(hasCommandModelArg ? (hasIsCallbackArg ? 2 : 1) : (hasIsCallbackArg ? 1 : 0))`), ensuring only real payload parameters appear in `SplitArgs`.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
tangge233
approved these changes
Mar 16, 2026
LinQingYuu
approved these changes
Mar 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
如果还有什么问题丢 comment,一块做了
Summary by Sourcery
扩展生命周期作用域源代码生成器,以支持更多命令处理程序参数,并与更新后的 IoC 命名空间保持一致。
新功能:
isCallback,该参数会由生成的代码透传。改进:
using语句以使用新的PCL.Core.App和PCL.Core.App.IoC命名空间。DependencyGroups,而不是通过 IoC 的静态访问入口进行调用。Original summary in English
Summary by Sourcery
Extend the lifecycle scope source generator to support additional command handler parameters and align it with updated IoC namespaces.
New Features:
Enhancements: