Namespaces
Group related commands under a shared path, scoped options, and their own help page. This follows the same mental model as ASP.NET's MapGroup.
The idiomatic pattern is to put commands as methods on a class, then register the class with AddNamespace<T>:
/// <summary>Commands under <c>storage</c>.</summary>
internal sealed class StorageCommands
{
/// <summary>List objects in the bucket.</summary>
public void List() => Console.WriteLine("storage:list");
}
app.AddNamespace<StorageCommands>("storage");
This creates the path: storage list.
Nested sub-groups are registered explicitly inside the namespace callback. There is no auto-discovery of nested types.
/// <summary>Commands under <c>storage</c>.</summary>
internal sealed class StorageCommands
{
/// <summary>List objects in the bucket.</summary>
public void List() => Console.WriteLine("storage:list");
}
/// <summary>Commands under <c>storage blob</c>.</summary>
internal sealed class BlobCommands
{
/// <summary>Upload a file.</summary>
/// <param name="path">-p,--path, Local file path.</param>
public void Upload(string path) => Console.WriteLine($"storage:blob:upload:{path}");
/// <summary>Download a file.</summary>
/// <param name="key">-k,--key, Object key.</param>
public void Download(string key) => Console.WriteLine($"storage:blob:download:{key}");
}
app.AddNamespace<StorageCommands>("storage", ns =>
{
ns.AddNamespace<BlobCommands>("blob");
});
- Register a nested namespace inside the parent callback.
This creates the following paths:
storage liststorage blob upload --path ./file.txtstorage blob download --key backups/db.sql
Add CommandNamespaceOptions<T>() inside the callback to attach scoped options to a namespace and its children:
app.AddNamespace<StorageCommands>("storage", ns =>
{
ns.CommandNamespaceOptions<StorageOptions>();
ns.AddNamespace<BlobCommands>("blob");
});
- Scoped options are inherited by all commands within the namespace, including nested sub-namespaces.
See Namespace options for details on the inheritance chain.
Put the <summary> (and optionally <remarks>) on the class T passed to AddNamespace<T>. The generator uses it as the namespace description in myapp storage --help and in the root command listing.
/// <summary>Manage blob and file storage resources.</summary>
/// <remarks>
/// Requires a storage connection string via <c>--connection-string</c>
/// or the <c>STORAGE_CONN</c> environment variable.
/// </remarks>
internal sealed class StorageCommands { … }
app.AddNamespace<StorageCommands>("storage", ns => { … });
The generator produces separate help printers for the namespace overview and each leaf command. This means <summary> and <remarks> on the namespace class only appear in the namespace-level help, not in individual command help.