Add IGlobalOptionsAccessor for typed access to global options#15
Merged
carldebilly merged 10 commits intomainfrom Apr 3, 2026
Merged
Add IGlobalOptionsAccessor for typed access to global options#15carldebilly merged 10 commits intomainfrom
carldebilly merged 10 commits intomainfrom
Conversation
Global options registered via AddGlobalOption<T> are now accessible outside handlers through IGlobalOptionsAccessor, registered in DI automatically. Middleware and DI factories can resolve it to read parsed values. Also adds UseGlobalOptions<T>() for typed class registration and a non-generic AddGlobalOption(name, typeName) overload accepting constraint-style type names.
Update commands, configuration reference, execution pipeline, parameter system, and best practices docs with global options accessor usage patterns and examples.
The non-generic AddGlobalOption(name, typeName) overload now resolves custom route constraints registered via AddRouteConstraint as string type. Adds tests for all built-in type names, custom constraints, enum conversion, ValueType preservation, and error cases.
UseGlobalOptions<T>() was registering the typed class as a singleton, causing stale values when global options changed between interactive REPL invocations. Changed to transient registration so each resolution reflects the latest parsed values. Added integration test verifying typed options update across invocations.
CLI-level global options now persist as session defaults across all interactive commands. Per-command overrides are temporary and revert to the session baseline on the next command.
Create a prototype instance of T to capture property initializer values
and pass them as registration defaults to AddGlobalOptionCore. This
ensures IGlobalOptionsAccessor returns correct defaults (e.g. 8080 for
Port { get; set; } = 8080) even when accessed outside the typed class.
- HasValue now returns false for baseline-inherited keys not explicitly provided in the current command - Bool-typed global options no longer consume the next positional token - Rename typeName parameter to constraintOrTypeName to reflect that custom route constraint names are also accepted - Add volatile to GlobalOptionsSnapshot fields for hosted session safety - PopulateInstance now uses configured NumericFormatProvider instead of hardcoded InvariantCulture
ToKebabCase now handles acronyms correctly: XMLPort → xml-port instead of x-m-l-port. Only inserts a hyphen at the start of an uppercase run or at the transition from uppercase run to lowercase. Added warning in best-practices.md that singleton DI factories capture global option values once and won't update in interactive mode.
PopulateInstance used HasValue() which only checks explicitly provided keys, causing session-baseline values to be skipped for typed options classes. Now checks GetRawValues() directly so baseline values are picked up correctly. Added "email" to the built-in type name resolution (resolves to string) to match its presence in ReservedConstraintNames.
SetSessionBaseline now rebuilds from only explicitly parsed keys, preventing stale values from leaking when the same app instance is used for multiple Run() calls.
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.
Summary
IGlobalOptionsAccessoris now registered in DI automatically, giving middleware, DI service factories, and handlers typed access to parsed global option values.UseGlobalOptions<T>()extension onReplAppallows declaring a typed class whose public settable properties become global options — the class is available via DI, populated from parsed values. Property names are converted to kebab-case (MaxRetries→--max-retries).AddGlobalOption(name, typeName)overload accepts constraint-style type names ("int","bool","guid","uri","date","timespan", etc.), matching the route constraint naming convention.GlobalOptionDefinitionnow preserves the declaredTypefromAddGlobalOption<T>()for help text generation and future validation.Examples
Dictionary-style access (works with both
CoreReplAppandReplApp):Typed class (requires
ReplAppwith MS DI):