Pipeline Steps
Each pipeline step operates on a strongly typed context, specified via a generic parameter.
A pipeline step consists of a single method and four optional metadata properties.
Property / Method | Type | Description |
---|---|---|
Name | string | A human-readable name for the step. Useful for logging, diagnostics, and documentation. |
Description | string | A brief description of what the step does. Primarily used for documentation and tooling. |
MayShortCircuit | bool | Indicates whether this step may choose to stop pipeline execution early. |
ShortCircuitCondition | string | Describes the condition under which this step may short-circuit. For documentation only. |
InvokeAsync(context, next) | Task | Executes the step's logic. To continue execution, call the next delegate. |
The optional metadata properties do not impact step registration or execution, but can be used to provide developer documentation about the step, and aide in troubleshooting.
Because pipeline steps are plain classes, you can inject dependencies through their constructors - enabling full integration with your existing services, business logic, and data access layers.
Extending PipelineStep<T>
Using the PipelineStep<T>
abstract class that provides default implementations for the optional metadata properties of IPipelineStep<T>
is the recommended approach to creating pipeline steps. You can optionally set the metadata properties in the constructor.
public class AddToContextStep : PipelineStep<StepContext>
{
public AddToContextStep()
{
// Sets the Name property
Name = "AddToContextStep";
}
public override async Task InvokeAsync(StepContext context, PipelineDelegate<StepContext> next, CancellationToken cancellationToken = default)
{
context.AddStep(Name);
await next(context, cancellationToken);
}
}
Short Circuiting Execution
Pipeline steps can short-circuit the pipeline execution by not calling the next()
delegate that is passed to the method.
public class ShortCircuitStep : PipelineStep<StepContext>
{
public ShortCircuitStep()
{
// Sets the Name property
Name = "ShortCircuitStep";
}
public override async Task InvokeAsync(StepContext context, PipelineDelegate<StepContext> next, CancellationToken cancellationToken = default)
{
context.AddStep(Name);
// If context.Steps is less than 2, the pipeline won't continue execution.
if (context.Steps >= 2)
await next(context, cancellationToken);
}
}
Adding the [PipelineStep]
Attribute
To be discoverable, each pipeline step must be decorated with the [PipelineStep]
attribute. This attribute defines the order in which pipeline steps should execute.
[PipelineStep(1)]
public class Step1 : PipelineStep<SampleContext>
{
// This is the first step that will execute in the pipeline
}
- Multiple steps that are not using the same context will not be impacted by using the same order value.
- Multiple steps that are using the same context and have the same order value will be ordered arbitrarily.
Adding a Step Filter
You can limit when a step will be registered by adding the Filter
parameter to the PipelineStep
attribute. This is useful to ensure that some steps will only be registered when the filter is applied during step discovery and registration.
[PipelineStep(2, "Development")]
public class Step2 : PipelineStep<SampleContext>
{
// This is the second step that will execute in the pipeline
}
- Steps without a
Filter
parameter will always be registered during the step discovery and registration process. - Steps with
Filter
parameter will only be registered if the same value is passed to the registration extension method.
Conclusion
Now that you've defined your pipeline steps, the next step is to discover and register them.