DumplingsDevs.Pipelines 0.0.14-alpha

This is a prerelease version of DumplingsDevs.Pipelines.
There is a newer version of this package available.
See the version list below for details.
dotnet add package DumplingsDevs.Pipelines --version 0.0.14-alpha                
NuGet\Install-Package DumplingsDevs.Pipelines -Version 0.0.14-alpha                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="DumplingsDevs.Pipelines" Version="0.0.14-alpha" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add DumplingsDevs.Pipelines --version 0.0.14-alpha                
#r "nuget: DumplingsDevs.Pipelines, 0.0.14-alpha"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install DumplingsDevs.Pipelines as a Cake Addin
#addin nuget:?package=DumplingsDevs.Pipelines&version=0.0.14-alpha&prerelease

// Install DumplingsDevs.Pipelines as a Cake Tool
#tool nuget:?package=DumplingsDevs.Pipelines&version=0.0.14-alpha&prerelease                

Pipelines

CI-main NuGet


πŸ“ <i> In almost every project I've been a part of, we had a set of reusable code that was used across multiple microservices. Each time, to maintain full control over types, I had to provide my own implementation for Commands, Queries, or Domain Events. This year was no different - a new client and once again the need to implement the same solution. That's why we decided to create 'Pipelines'.</i>


πŸ›  'Pipelines' is perfectly tailored for creating pipelines for Queries, Commands, Domain Events, any other pipeline utilizing your OWN types. Everywhere in your app will remain unaware of 'Pipelines' usage, with the exception of pipeline registration. If you're aiming to separate code execution logic from its invocation, such as with the Mediation pattern, this tool offers the flexibility you require.


βœ… <b>Fastest on the Market</b> - Pipelines guarantees rapid performance, thanks to bypassing the reflection mechanism to find the appropriate handler. Efficiency is at the core of design!

βœ… <b>Unparalleled Flexibility</b> - With the capability to craft pipelines based on your own types, you have absolute control over the method inputs and the returned results

βœ… <b>Craft Multiple Pipelines</b> - The freedom to create any number of pipelines within your application, each one can be tailor-made for its specific use case

βœ… <b>Minimal Dependency</b> - Developers will see the reference to 'Pipeline' namespace exclusively when they're registering with the AddPipeline() method. Elsewhere in the application, the presence of this library remains undetected.

βœ… <b>Type Validators</b> - If you inadvertently provide inconsistent types, such as discrepancies between the dispatcher and handler, type validators will alert you immediately with exceptions, ensuring the integrity and correctness of your configurations.

βœ… <b>Designed with Developers in Mind</b> - Constructed with the developer's requirements at heart, our tool simplifies and accelerates your work, always upholding top-notch standards.

πŸ“¦ Installation


dotnet add package DumplingsDevs.Pipelines
dotnet add package DumplingsDevs.Pipelines.WrapperDispatcherGenerator

πŸš€ Quick Start


1️⃣ Define your own types

1.1 Input

The "Input" acts as the initial parameter for Handler and Dispatcher methods, guiding the search for the relevant Handler.

<details> <summary style="color: green">πŸ“œ Show me code </summary>

public interface IInput<TResult> where TResult: class{ } 

</details>

1.2 Handler

Handlers house the application logic and can generate both synchronous and asynchronous results.

<details> <summary style="color: green">πŸ“œ Show me code </summary>

public interface IHandler<in TInput, TResult> where TInput : IInput<TResult> where TResult: class
{
    public Task<TResult> HandleAsync(TInput input, CancellationToken token);
}

</details>

1.3 Dispatcher

Serving as a bridge between inputs and their respective handlers, the Dispatcher ensures the appropriate Handler is triggered for a given Input.

<details> <summary style="color: green">πŸ“œ Show me code </summary>

public interface IDispatcher
{
    public Task<TResult> SendAsync<TResult>(IInput<TResult> input, CancellationToken token) where TResult : class;
}

</details>

2️⃣ Implement first decorator (optional step)

Analogous to Middlewares in .NET. Think of them as layers of logic that execute before or after the handler.

<details> <summary style="color: green">πŸ“œ Show me code </summary>

public class LoggingDecorator<TInput, TResult> : IHandler<TInput, TResult> where TInput : IInput<TResult> where TResult : class
{
    private readonly IHandler<TInput, TResult> _handler;
    private readonly ILogger _logger;
    
    public LoggingDecorator(IHandler<TInput, TResult> handler, ILogger logger)
    {
        _handler = handler;
        _logger = logger;
    }

    public async Task<TResult> HandleAsync(TInput request, CancellationToken token)
    {
        _logger.Log(LogLevel.Information,"Executing handler for input {0}", typeof(TInput));
        var result = await _handler.HandleAsync(request, token);
        _logger.Log(LogLevel.Information,"Executed handler for input {0}", typeof(TInput));

        return result;
    }
}

</details>

3️⃣ Implement first handler

3.1 Input and Result

<details> <summary style="color: green">πŸ“œ Show me code </summary>

public record ExampleInput(string Value) : IInput<ExampleCommandResult>;
public record ExampleCommandResult(string Value);

</details>

3.2 Handler

<details> <summary style="color: green">πŸ“œ Show me code </summary>

public class ExampleHandler : IHandler<ExampleInput, ExampleCommandResult>
{
    public Task<ExampleCommandResult> HandleAsync(ExampleInput input, CancellationToken token)
    {
        return Task.FromResult(new ExampleCommandResult(input.Value));
    }
}

</details>

4️⃣ Register pipeline

In your application's initialization, such as Startup.cs:

<b> IMPORTANT! All provided types must be specified using the typeof() method! </b>

<details> <summary style="color: green">πŸ“œ Show me code </summary>

var handlersAssembly = //Assembly where handlers assembly are implemented
var dispatcherAssembly = //Assembly where AddPipeline gets invoked

_services
    .AddPipeline()
    .AddInput(typeof(IInput<>))
            .AddHandler(typeof(IHandler<,>), handlersAssembly)
            .AddDispatcher<IDispatcher>(dispatcherAssembly)
              .WithDecorator(typeof(LoggingDecorator<,>));

</details>

5️⃣ Example Usage (Fluent API .NET)

<details> <summary style="color: green">πŸ“œ Show me code </summary>

public static void CreateExampleEndpoint(this WebApplication app)
    {
        app.MapPost("/example", async (ExampleInput request, IDispatcher dispatcher, CancellationToken token) =>
        {
            var result = await dispatcher.SendAsync(input,token);
            return Results.Ok();
        });
    }

</details>


πŸ“š Detailed documentation



⚠️ Limitations

  • Pipelines in which multiple handlers will be handled for one input must have a Task or void return type.
  • Cannot create a Pipeline that returns both generic and non-generic types.

πŸ›€ Roadmap

  • ADR Documentation: Record key architectural decisions made during implementation using ADRs.
  • Dependency Injection Scope Choice: Provide an option to decide whether or not to create a Dependency Injection Scope in Dispatchers.
  • Code Cleanup: Refine and tidy up the codebase post-MVP, paving the way for new feature development.
  • Parallel Pipeline: Introduce a pipeline to facilitate parallel execution of multiple handlers.
  • Stream Pipeline: Implement support for streaming pipelines.
  • Decorator Performance Optimization: Improve performance, especially concerning the use of ActivatorUtilities.CreateInstance().

πŸ₯ŸπŸ’‘ The Dumplings Behind the Magic

Hey there! We're Dumplings Devs, made up of <a href="https://pl.linkedin.com/in/matwroblewski">Mateusz WrΓ³blewski</a> and <a href="https://pl.linkedin.com/in/kamil-bytner">Kamil Bytner</a>. We're passionate about software and always up for a coding challenge.

Product Compatible and additional computed target framework versions.
.NET net5.0 is compatible.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.2 184 9/16/2023
1.0.1 182 9/10/2023
1.0.0 153 9/4/2023
0.0.14-alpha 129 9/4/2023
0.0.13-alpha 121 9/4/2023
0.0.12-alpha 118 9/3/2023
0.0.11-alpha 122 8/31/2023
0.0.10-alpha 128 8/29/2023
0.0.9-alpha 131 8/29/2023
0.0.8-alpha 122 8/29/2023
0.0.7-alpha 133 8/28/2023
0.0.6-alpha 123 8/27/2023
0.0.5-alpha 130 8/24/2023
0.0.4-alpha 127 8/6/2023
0.0.3-alpha 132 8/5/2023
0.0.2-alpha 126 8/1/2023
0.0.1-alpha 141 8/1/2023