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