When your command needs to accept configuration values, environment variables, or other key-value pairs, use dictionary-based option types. Spectre.Console.Cli supports IDictionary<TKey, TValue>, ILookup<TKey, TValue>, and IReadOnlyDictionary<TKey, TValue>.
What We're Building
A configuration command accepting key-value pairs like --value port=8080, plus lookups where one key can have multiple values:
Accept Key-Value Pairs
Use IDictionary<string, T> to collect key-value pairs. Users specify values in key=value format:
public class Settings : CommandSettings
{
// IDictionary<string, int> - key=value pairs with typed values
// Usage: --value port=8080 --value timeout=30
[CommandOption("--value <VALUE>")]
[Description("Configuration values in key=value format (e.g., port=8080)")]
public IDictionary<string, int>? Values { get; set; }
// ILookup<string, string> - allows multiple values per key
// Usage: --lookup env=dev --lookup env=test --lookup region=us
[CommandOption("--lookup <VALUE>")]
[Description("Lookup values allowing multiple entries per key")]
public ILookup<string, string>? Lookups { get; set; }
// IReadOnlyDictionary<string, string> - immutable key-value pairs
// Usage: --readonly name=myapp --readonly version=1.0
[CommandOption("--readonly <VALUE>")]
[Description("Read-only configuration values")]
public IReadOnlyDictionary<string, string>? ReadOnlyValues { get; set; }
}
Users invoke the command with repeated options:
myapp --value port=8080 --value timeout=30 --value retries=3
The framework parses the key=value format automatically and converts the value to the specified type (in this case, int).
Collect Multiple Values per Key
When a key can have multiple associated values, use ILookup<TKey, TValue>. Unlike IDictionary, a lookup allows multiple entries for the same key:
myapp --lookup env=dev --lookup env=staging --lookup env=prod --lookup region=us
Access grouped values in your command:
foreach (var group in settings.Lookups)
{
Console.WriteLine($"{group.Key}:");
foreach (var value in group)
{
Console.WriteLine($" - {value}");
}
}
Output:
env:
- dev
- staging
- prod
region:
- us
Use Read-Only Dictionaries
For immutable configuration that shouldn't be modified after parsing, use IReadOnlyDictionary<TKey, TValue>:
[CommandOption("--setting <VALUE>")]
public IReadOnlyDictionary<string, string>? Settings { get; set; }
This provides the same parsing behavior as IDictionary but returns a read-only collection.
Supported Key-Value Types
Both the key and value types can use any type that Spectre.Console.Cli can convert:
| Pattern | Example Usage |
|---|---|
IDictionary<string, int> |
--opt key=42 |
IDictionary<string, bool> |
--opt flag=true |
IDictionary<int, string> |
--opt 1=first |
ILookup<string, string> |
--opt tag=a --opt tag=b |
See Also
- Defining Commands and Arguments - Basic argument and option patterns
- Type Converters - Type conversion reference