Add [Bind] attribute and typed ConfigureGlobalOptions<T>()#237
Open
Mpdreamz wants to merge 1 commit intoCysharp:masterfrom
Open
Add [Bind] attribute and typed ConfigureGlobalOptions<T>()#237Mpdreamz wants to merge 1 commit intoCysharp:masterfrom
Mpdreamz wants to merge 1 commit intoCysharp:masterfrom
Conversation
[Bind] Attribute - Class-Based Parameter Binding: - Bind command parameters to class/record properties and constructor parameters - Properties become CLI options (--property-name) with automatic kebab-case conversion - Support for required modifier, [Argument] for positional args, and XML doc aliases - Multiple [Bind] parameters with prefix support to namespace options - Mixed constructor and property binding for flexible initialization Typed Global Options: - ConfigureGlobalOptions<T>() for type-based global options without manual builder wiring - Any class/record with parameterless constructor works (no special attribute required) - XML doc comments for aliases and descriptions - Global options parsed before command routing, can appear anywhere on command line - Properly populates ConsoleAppContext.GlobalOptions for filters [Bind] + Global Options Inheritance: - When [Bind] type inherits from the global options type, inherited properties are automatically populated from parsed global options - Enables shared configuration across commands without repetition - Global options flow through to command-specific [Bind] types Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Contributor
Author
|
@neuecc gentle bump just because I'm curious about your thoughts on the direction here :) |
Member
|
There seems to be no mention of it, but is it the same request as the one in #133 ? |
Contributor
Author
|
Its similar but not the same: this PR does not require the bound class/record class to come from DI it also does not tie the bound arg to be the command handler itself. This PR could serve as a basis for that though to support both |
Member
|
I don't think AsParameters is related to DI, though... |
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.
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