RSCG – DeeDee

RSCG – DeeDee
 
 

name DeeDee
nuget https://www.nuget.org/packages/DeeDee/
link https://github.com/joh-pot/DeeDee/
author joh-pot

Mediatr generated data

 

This is how you can use DeeDee .

The code that you start with is


<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
	<PropertyGroup>
		<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
		<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
	</PropertyGroup>
	<ItemGroup>
		<PackageReference Include="DeeDee" Version="2.0.0" />
		<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
		
	</ItemGroup>

</Project>


The code that you will use is


Console.WriteLine("Hello, World!");
ServiceCollection services = new ();
DeeDeeDemo.DeeDee.Generated.IocExtensions.AddDispatcher(services);

services.AddSingleton(typeof(IPipelineAction<Ping, Pong>), typeof(GenericLoggerHandler)); // This will run 1st

var serviceProvider = services.BuildServiceProvider();

var mediator = serviceProvider.GetRequiredService<DeeDeeDemo.DeeDee.Generated.Models.IDispatcher>();
var id = Guid.NewGuid();
var request = new Ping(id);

var response = mediator.Send(request);

Console.WriteLine("-----------------------------------");
Console.WriteLine("ID: " + id);
Console.WriteLine(request);
Console.WriteLine(response);




public sealed record Ping(Guid Id) : IRequest<Pong>;

public sealed record Pong(Guid Id);


public sealed class PingHandler : IPipelineAction<Ping, Pong>
{

    public Pong Invoke(Ping request, ref PipelineContext<Pong> context, Next<Pong> next)
    {
        Console.WriteLine("4) Returning pong!");
        return new Pong(request.Id);
    }
}



public sealed class GenericLoggerHandler : IPipelineAction<Ping, Pong>
{
    public Pong Invoke(Ping request, ref PipelineContext<Pong> context, Next<Pong> next)
    {
        Console.WriteLine("1) Running logger handler");
        try
        {
            var response = next(request , ref context);
            Console.WriteLine("5) No error!");
            return response;
        }
        catch (Exception ex)
        {
            Console.WriteLine("error:" + ex.Message);
            throw;
        }
    }
}

 

The code that is generated is

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;
using DeeDee.Models;
using ServiceProvider = DeeDee.Models.ServiceProvider;

namespace DeeDeeDemo.DeeDee.Generated.Models
{
    public class Dispatcher : IDispatcher
    {
        private readonly ServiceProvider _serviceFactory;
        private readonly Lazy<Next<Pong>> _Ping_Pong_lazy;
        public Dispatcher(ServiceProvider service)
        {
            _serviceFactory = service;
            _Ping_Pong_lazy = new Lazy<Next<Pong>>(Build<Ping, Pong>);
        }

        public Pong Send(Ping request)
        {
            var context = new PipelineContext<Pong>();
            Next<Pong> builtPipeline = _Ping_Pong_lazy.Value;
            return builtPipeline(request, ref context);
        }

        private NextAsync BuildAsync<TRequest>()
            where TRequest : IRequest
        {
            {
                var actions = _serviceFactory.GetServices<IPipelineActionAsync<TRequest>>();
                var builtPipeline = actions.Aggregate((NextAsync)((req, ctx, tkn) => Task.CompletedTask), (next, pipeline) => (req, ctx, tkn) => pipeline.InvokeAsync((TRequest)req, ctx, next, tkn));
                return builtPipeline;
            }
        }

        private Next Build<TRequest>()
            where TRequest : IRequest
        {
            {
                var actions = _serviceFactory.GetServices<IPipelineAction<TRequest>>();
                var builtPipeline = actions.Aggregate((Next)((IRequest req, ref PipelineContext ctx) =>
                {
                    {
                    }
                }), (next, pipeline) => (IRequest req, ref PipelineContext ctx) => pipeline.Invoke((TRequest)req, ref ctx, next));
                return builtPipeline;
            }
        }

        private NextAsync<TResponse> BuildAsync<TRequest, TResponse>()
            where TRequest : IRequest<TResponse>
        {
            {
                var actions = _serviceFactory.GetServices<IPipelineActionAsync<TRequest, TResponse>>();
                var builtPipeline = actions.Aggregate((NextAsync<TResponse>)((req, ctx, tkn) => Task.FromResult(ctx.Result)), (next, pipeline) => (req, ctx, tkn) => pipeline.InvokeAsync((TRequest)req, ctx, next, tkn));
                return builtPipeline;
            }
        }

        private Next<TResponse> Build<TRequest, TResponse>()
            where TRequest : IRequest<TResponse>
        {
            {
                var actions = _serviceFactory.GetServices<IPipelineAction<TRequest, TResponse>>();
                var builtPipeline = actions.Aggregate((Next<TResponse>)((IRequest<TResponse> req, ref PipelineContext<TResponse> ctx) => ctx.Result), (next, pipeline) => (IRequest<TResponse> req, ref PipelineContext<TResponse> ctx) => pipeline.Invoke((TRequest)req, ref ctx, next));
                return builtPipeline;
            }
        }
    }
}
using System;
using System.Threading;
using System.Threading.Tasks;
using DeeDee.Models;

namespace DeeDeeDemo.DeeDee.Generated.Models
{
    public interface IDispatcher
    {
        public Pong Send(Ping request);
    }
}

            using System;
            using System.Linq;
            using System.Reflection;
            using DeeDee.Models;
            using DeeDeeDemo.DeeDee.Generated.Models;
            using Microsoft.Extensions.DependencyInjection;
            using ServiceProvider = DeeDee.Models.ServiceProvider;
            namespace DeeDeeDemo.DeeDee.Generated

            {
                internal static class IocExtensions
                {
                    public static IServiceCollection AddDispatcher(this IServiceCollection services, Lifetime lifetime = Lifetime.Singleton)
                    {
                        switch(lifetime)
                        {
                            case Lifetime.Singleton:
                                services.AddSingleton<IDispatcher, Dispatcher>();
                                services.AddSingleton<ServiceProvider>(ctx => ctx.GetRequiredService);
                                break;

                            case Lifetime.Scoped:
                                services.AddScoped<IDispatcher, Dispatcher>();
                                services.AddScoped<ServiceProvider>(ctx => ctx.GetRequiredService);
                                break;

                            case Lifetime.Transient:
                                services.AddTransient<IDispatcher, Dispatcher>();
                                services.AddTransient<ServiceProvider>(ctx => ctx.GetRequiredService);
                                break;
                        }
                        
                        RegisterPipelineActions(services);
                        
                        return services;
                    }

                    private static void RegisterPipelineActions(IServiceCollection services)
                    {
                        var pipelineTypes = AppDomain
                            .CurrentDomain
                            .GetAssemblies()
                            .SelectMany
                            (
                                a => a.GetTypes().Where
                                (
                                   x => !x.IsInterface &&
                                        !x.IsAbstract &&
                                        x.GetInterfaces()
                                            .Any
                                            (
                                                y => y.Name.Equals(typeof(IPipelineActionAsync<,>).Name,
                                                         StringComparison.InvariantCulture) ||
                                                     y.Name.Equals(typeof(IPipelineActionAsync<>).Name,
                                                         StringComparison.InvariantCulture) ||
                                                     y.Name.Equals(typeof(IPipelineAction<>).Name,
                                                         StringComparison.InvariantCulture) ||
                                                     y.Name.Equals(typeof(IPipelineAction<,>).Name, StringComparison.InvariantCulture)
                                            )
                                ).GroupBy(type => type.GetInterfaces()[0]).SelectMany(g => g.OrderByDescending(s => s.GetCustomAttribute<StepAttribute>()?.Order))
                            );

                        foreach (var type in pipelineTypes)
                        {
                            foreach (var implementedInterface in type.GetInterfaces())
                            {
                                var bindAs = type.GetCustomAttribute<BindAsAttribute>();
                                switch (bindAs?.Lifetime)
                                {
                                    case Lifetime.Singleton:
                                        services.AddSingleton(implementedInterface, type);
                                        break;
                                    case Lifetime.Scoped:
                                        services.AddScoped(implementedInterface, type);
                                        break;  
                                    case Lifetime.Transient:
                                        services.AddTransient(implementedInterface, type);
                                        break;
                                    default:
                                        services.AddSingleton(implementedInterface, type);
                                        break;
                                }
                                
                            }
                        } 
                    }
                }
            }

Code and pdf at

https://ignatandrei.github.io/RSCG_Examples/v2/docs/DeeDee