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
Leave a Reply