Add [Bind] attribute and typed ConfigureGlobalOptions<T>() #237
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.
This a rather large PR sorry in advance!
I often run in to the need to be able to bind to records/classes as command arguments.
E.g a worst case is this rather large command: https://github.com/elastic/docs-builder/blob/main/src/tooling/docs-builder/Commands/IndexCommand.cs
This adds support for binding to records/classes (constructor and property binding) without reflection, source generated. It supports inheritance including inheriting from global options for which a new
ConfigureGlobalOptions<T>()is introduced.I used Claude Code to help me code this and help generate extensive tests.
Add
[Bind]attribute for class-based parameter binding and typed ConfigureGlobalOptions()Summary
This PR introduces two major features that simplify CLI application development:
[Bind]attribute - Bind command parameters to class/record properties instead of inline parametersConfigureGlobalOptions<T>()- Define global options as a type without manual builder wiring[Bind]+ Global Options inheritance - Automatically flow global options into command-specific typesAll features are fully AOT-compatible with source-generated parsing code.
[Bind] Attribute - Class-Based Parameter Binding
Why?
Commands with many parameters become unwieldy when defined inline.
[Bind]enables organizing parameters into reusable classes/records, supporting primary constructors, therequiredmodifier, and XML doc comments for aliases.Basic Usage
Required Parameters
Positional Arguments
Aliases via XML Doc
Multiple [Bind] with Prefixes
Typed ConfigureGlobalOptions()
Why?
The existing builder-based
ConfigureGlobalOptions((ref builder) => ...)requires manual wiring. The typed approach lets you define global options as a simple class/record - no special attributes required.Usage
Global options are parsed before command routing and can appear anywhere on the command line.
[Bind] + Global Options Inheritance
Why?
When commands need both global options and command-specific options, inheritance eliminates repetition. The
[Bind]type automatically receives global option values when it inherits from the registered global options type.Usage
Help Text
Global options appear in root help under "Global Options:" section. Command help shows only command-specific options (inherited global options are excluded to avoid duplication).
Test Coverage
tests/ConsoleAppFramework.GeneratorTests/Bind/- Comprehensive [Bind] teststests/ConsoleAppFramework.GeneratorTests/GlobalOptions/- Typed global options testsNativeAotTests