RSCG – Immediate.Handlers

RSCG – Immediate.Handlers
 
 

name Immediate.Handlers
nuget https://www.nuget.org/packages/Immediate.Handlers/
link https://github.com/immediateplatform/Immediate.Handlers
author Stuart Turner

Generating mediator like handlers

 

This is how you can use Immediate.Handlers .

The code that you start with is


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

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
	<PropertyGroup>
		<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
		<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
	</PropertyGroup>
	<ItemGroup>
		<PackageReference Include="Immediate.Handlers" Version="1.6.1" />
		<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
		<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.1" />		
	</ItemGroup>

</Project>


The code that you will use is



Console.WriteLine("Hello, World!");
ServiceCollection services = new ();
services.AddSingleton<ILoggerFactory, NullLoggerFactory>();
services.AddSingleton(typeof(ILogger<>), typeof(NullLogger<>));
services.AddHandlers();
services.AddBehaviors();
IHandler<Ping, Pong> handler = services.BuildServiceProvider().GetRequiredService<IHandler<Ping, Pong>>();
var id = Guid.NewGuid();
var request = new Ping(id);
var pong = await handler.HandleAsync(request, CancellationToken.None);
Console.WriteLine($"Got pong with id {pong.Id}!");



using Immediate.Handlers.Shared;

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

public sealed record Pong(Guid Id);


[Handler]
[Behaviors(
    typeof(LoggingBehavior<,>)
)]
public static partial class PingHandler //: IPipelineAction<Ping, Pong>
{

    private static async ValueTask<Pong> HandleAsync(Ping request, CancellationToken token)
    {
        await Task.Delay(1000);
        Console.WriteLine("Returning pong!");
        return new Pong(request.Id);
    }
}




public sealed class LoggingBehavior<TRequest, TResponse>(ILogger<LoggingBehavior<TRequest, TResponse>>? logger)
    : Behavior<TRequest, TResponse>
{
    public override async ValueTask<TResponse> HandleAsync(TRequest request, CancellationToken cancellationToken)
    {
        Console.WriteLine("I am a logging behaviour");
        logger?.LogInformation("LoggingBehavior.Enter");
        var response = await Next(request, cancellationToken);
        logger?.LogInformation("LoggingBehavior.Exit");
        return response;
    }
}


global using Microsoft.Extensions.DependencyInjection;
global using Immediate.Handlers.Shared;
global using Microsoft.Extensions.Logging;
global using Mediator;
global using Microsoft.Extensions.Logging.Abstractions;


 

The code that is generated is

using Microsoft.Extensions.DependencyInjection;

#pragma warning disable CS1591

partial class PingHandler
{
	public sealed partial class Handler : global::Immediate.Handlers.Shared.IHandler<global::Ping, global::Pong>
	{
		private readonly global::PingHandler.HandleBehavior _handleBehavior;
		private readonly global::LoggingBehavior<global::Ping, global::Pong> _loggingBehavior;

		public Handler(
			global::PingHandler.HandleBehavior handleBehavior,
			global::LoggingBehavior<global::Ping, global::Pong> loggingBehavior
		)
		{
			var handlerType = typeof(PingHandler);

			_handleBehavior = handleBehavior;

			_loggingBehavior = loggingBehavior;
			_loggingBehavior.HandlerType = handlerType;

			_loggingBehavior.SetInnerHandler(_handleBehavior);
		}

		public async global::System.Threading.Tasks.ValueTask<global::Pong> HandleAsync(
			global::Ping request,
			global::System.Threading.CancellationToken cancellationToken = default
		)
		{
			return await _loggingBehavior
				.HandleAsync(request, cancellationToken)
				.ConfigureAwait(false);
		}
	}

	[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
	public sealed class HandleBehavior : global::Immediate.Handlers.Shared.Behavior<global::Ping, global::Pong>
	{

		public HandleBehavior(
		)
		{
		}

		public override async global::System.Threading.Tasks.ValueTask<global::Pong> HandleAsync(
			global::Ping request,
			global::System.Threading.CancellationToken cancellationToken
		)
		{
			return await global::PingHandler
				.HandleAsync(
					request
					, cancellationToken
				)
				.ConfigureAwait(false);
		}
	}

	[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
	public static IServiceCollection AddHandlers(
		IServiceCollection services,
		ServiceLifetime lifetime = ServiceLifetime.Scoped
	)
	{
		services.Add(new(typeof(global::PingHandler.Handler), typeof(global::PingHandler.Handler), lifetime));
		services.Add(new(typeof(global::Immediate.Handlers.Shared.IHandler<global::Ping, global::Pong>), typeof(global::PingHandler.Handler), lifetime));
		services.Add(new(typeof(global::PingHandler.HandleBehavior), typeof(global::PingHandler.HandleBehavior), lifetime));
		return services;
	}
}

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;

#pragma warning disable CS1591

namespace Mediator;

public static class HandlerServiceCollectionExtensions
{
	public static IServiceCollection AddBehaviors(
		this IServiceCollection services)
	{
		services.TryAddTransient(typeof(global::LoggingBehavior<,>));
		
		return services;
	}

	public static IServiceCollection AddHandlers(
		this IServiceCollection services,
		ServiceLifetime lifetime = ServiceLifetime.Scoped
	)
	{
		global::PingHandler.AddHandlers(services, lifetime);
		
		return services;
	}
}

Code and pdf at

https://ignatandrei.github.io/RSCG_Examples/v2/docs/Immediate.Handlers