-
Notifications
You must be signed in to change notification settings - Fork 13
Defining custom directives
Adam Bajguz edited this page Apr 5, 2021
·
12 revisions
To define a custom directive, just create a new class that implements the IDirective
or IPipelinedDirective
interface and annotate it with [Directive]
attribute:
[Directive(BuiltInDirectives.Debug, Description = "Starts a debugging mode. Application will wait for debugger to be attached before proceeding.")]
public sealed class DebugDirective : IPipelinedDirective
{
/// <inheritdoc/>
public ValueTask OnInitializedAsync(CancellationToken cancellationToken)
{
return default;
}
/// <inheritdoc/>
public async ValueTask HandleAsync(ICliContext context, CommandPipelineHandlerDelegate next, CancellationToken cancellationToken)
{
#if NET5_0
int processId = Environment.ProcessId;
#else
int processId = Process.GetCurrentProcess().Id;
#endif
IConsole console = context.Console;
console.Output.WithForegroundColor(ConsoleColor.Green, (output) => output.WriteLine($"Attach debugger to PID {processId} to continue."));
Debugger.Launch();
while (!Debugger.IsAttached)
await Task.Delay(100, cancellationToken);
await next();
}
}
To facilitate both asynchronous and synchronous execution, OnInitializedAsync
and HandleAsync
methods return a ValueTask
. In synchronous implementation, we can just put return default
at the end, while in an asynchronous we can use the async
/await
keywords instead.
Similarly to commands, in every directive it is possible to define a description and a manual with [Directive]
attribute. [Directive]
attribute provides also an easy way for excluding a command from execution in normal mode through InteractiveModeOnly
property.
Getting started
Advanced features
- Reporting errors
- Exception handling
- Metadata and startup message
- Graceful cancellation
- Dependency injection
- Middleware pipeline
- Environment variables
Utilities
Tests
Misc