Skip to content

Middleware pipeline

Adam Bajguz edited this page Oct 2, 2020 · 25 revisions

Typin uses middleware pipeline to execute commands. The pipeline starts just after parsing command input. By default it consists only of Typin middlewares that are always executed at the end of the pipeline, just before IMiddlewareExtensions.PipelineTermination action.

typin-middleware-pipeline

Default/Internal Typin middleware pipeline structure: ResolveCommandSchema -> HandleVersionOption -> ResolveCommandInstance -> HandleInteractiveDirective -> HandleHelpOption -> HandleInteractiveCommands -> ExecuteCommand.

Default/Internal Typin middleware pipeline execution visualization:

==============================================================================================================================
 Middleware type name                                       | Assembly
==============================================================================================================================
 Typin.Internal.Pipeline.ResolveCommandSchema               | Typin, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null
 Typin.Internal.Pipeline.HandleVersionOption                | Typin, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null
 Typin.Internal.Pipeline.ResolveCommandInstance             | Typin, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null
 Typin.Internal.Pipeline.HandleInteractiveDirective         | Typin, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null
 Typin.Internal.Pipeline.HandleHelpOption                   | Typin, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null
 Typin.Internal.Pipeline.HandleInteractiveCommands          | Typin, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null
 Typin.Internal.Pipeline.ExecuteCommand                     | Typin, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null
 <PipelineTermination>                                      |
 Typin.Internal.Pipeline.ExecuteCommand                     | Typin, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null
 Typin.Internal.Pipeline.HandleInteractiveCommands          | Typin, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null
 Typin.Internal.Pipeline.HandleHelpOption                   | Typin, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null
 Typin.Internal.Pipeline.HandleInteractiveDirective         | Typin, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null
 Typin.Internal.Pipeline.ResolveCommandInstance             | Typin, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null
 Typin.Internal.Pipeline.HandleVersionOption                | Typin, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null
 Typin.Internal.Pipeline.ResolveCommandSchema               | Typin, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null
==============================================================================================================================

Writing custom middlewares

To define a middleware, just create a new class that implements the IMiddleware interface:

public sealed class ExampleMiddleware : IMiddleware
{
    public async Task HandleAsync(ICliContext context, CommandPipelineHandlerDelegate next, CancellationToken cancellationToken)
    {
        context.Console.Output.WriteLine("-- Before command execution --");

        await next();

        context.Console.Output.WriteLine("-- After command execution-- ");
    }
}

To implement IMiddleware, the class needs to define an HandleAsync method. This is the method that gets by called Typin when the pipeline is executed.

It is also possible to using dependency injection in IMiddleware implementation class, e.g.,

public sealed class ExampleMiddleware : IMiddleware
{
    private readonly IConsole _console;

    public ExampleMiddleware (IConsole console)
    {
        _console = console;
    }

    public async Task HandleAsync(ICliContext context, CommandPipelineHandlerDelegate next, CancellationToken cancellationToken)
    {
        context.Console.Output.WriteLine("-- Before command execution --");

        await next();

        _console.Output.WriteLine("-- After command execution-- ");
    }
}
Clone this wiki locally