RSCG – Mediator

RSCG – Mediator
 
 

name Mediator
nuget https://www.nuget.org/packages/Mediator.SourceGenerator
https://www.nuget.org/packages/Mediator.Abstractions
link https://github.com/martinothamar/Mediator
author Martin Othamar

Gnerating mediator data without reflection

 

This is how you can use Mediator .

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="Mediator.Abstractions" Version="2.1.5" />
		<PackageReference Include="Mediator.SourceGenerator" Version="2.1.5" OutputItemType="Analyzer">
		  <PrivateAssets>all</PrivateAssets>
		  <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
		</PackageReference>
		<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
		
	</ItemGroup>

</Project>


The code that you will use is


Console.WriteLine("Hello, World!");
var services = new ServiceCollection();
services.AddMediator();
services.AddSingleton(typeof(IPipelineBehavior<,>), typeof(GenericLoggerHandler<,>)); // This will run 1st

var serviceProvider = services.BuildServiceProvider();

var mediator = serviceProvider.GetRequiredService<IMediator>();
var id = Guid.NewGuid();
var request = new Ping(id);

var response = await mediator.Send(request);

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




public sealed class GenericLoggerHandler<TMessage, TResponse> : IPipelineBehavior<TMessage, TResponse>
    where TMessage : IMessage
{
    public async ValueTask<TResponse> Handle(TMessage message, CancellationToken cancellationToken, MessageHandlerDelegate<TMessage, TResponse> next)    
    {
        Console.WriteLine("1) Running logger handler");
        try
        {
            var response = await next(message, cancellationToken);
            Console.WriteLine("5) No error!");
            return response;
        }
        catch (Exception ex)
        {
            Console.WriteLine("error:"+ex.Message);
            throw;
        }
    }

}



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

public sealed record Pong(Guid Id);


public sealed class PingHandler : IRequestHandler<Ping, Pong>
{
    public ValueTask<Pong> Handle(Ping request, CancellationToken cancellationToken)
    {
        Console.WriteLine("4) Returning pong!");
        return new ValueTask<Pong>(new Pong(request.Id));
    }
}


 

The code that is generated is

// <auto-generated>
//     Generated by the Mediator source generator.
// </auto-generated>

#pragma warning disable CS8019 // Unused usings
#pragma warning disable CS8321 // Unused local function
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System.Linq;

using SD = global::Microsoft.Extensions.DependencyInjection.ServiceDescriptor;

namespace Microsoft.Extensions.DependencyInjection
{
    /// <summary>
    /// DI extensions for Mediator.
    /// </summary>
    [global::System.CodeDom.Compiler.GeneratedCode("Mediator.SourceGenerator", "2.1.0.0")]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.Diagnostics.DebuggerStepThroughAttribute]
    public static class MediatorDependencyInjectionExtensions
    {
        /// <summary>
        /// Adds the Mediator implementation and handlers of your application.
        /// </summary>
        public static IServiceCollection AddMediator(this IServiceCollection services)
        {
            return AddMediator(services, null);
        }

        internal sealed class Dummy { }

        /// <summary>
        /// Adds the Mediator implementation and handlers of your application, with specified options.
        /// </summary>
        public static IServiceCollection AddMediator(this IServiceCollection services, global::System.Action<global::Mediator.MediatorOptions> options)
        {
            var opts = new global::Mediator.MediatorOptions();
            if (options != null)
                options(opts);

            var configuredViaAttribute = false;
            if (opts.ServiceLifetime != global::Microsoft.Extensions.DependencyInjection.ServiceLifetime.Singleton && !configuredViaAttribute)
            {
                var errMsg = "Invalid configuration detected for Mediator. ";
                errMsg += "Generated code for 'Singleton' lifetime, but got '" + opts.ServiceLifetime + "' lifetime from options. ";
                errMsg += "This means that the source generator hasn't seen the 'AddMediator' method call during compilation. ";
                errMsg += "Make sure that the 'AddMediator' method is called from the project that references the Mediator.SourceGenerator package.";
                throw new global::System.Exception(errMsg);
            }


            services.Add(new SD(typeof(global::Mediator.Mediator), typeof(global::Mediator.Mediator), global::Microsoft.Extensions.DependencyInjection.ServiceLifetime.Singleton));
            services.TryAdd(new SD(typeof(global::Mediator.IMediator), sp => sp.GetRequiredService<global::Mediator.Mediator>(), global::Microsoft.Extensions.DependencyInjection.ServiceLifetime.Singleton));
            services.TryAdd(new SD(typeof(global::Mediator.ISender), sp => sp.GetRequiredService<global::Mediator.Mediator>(), global::Microsoft.Extensions.DependencyInjection.ServiceLifetime.Singleton));
            services.TryAdd(new SD(typeof(global::Mediator.IPublisher), sp => sp.GetRequiredService<global::Mediator.Mediator>(), global::Microsoft.Extensions.DependencyInjection.ServiceLifetime.Singleton));

            services.TryAdd(new SD(typeof(global::PingHandler), typeof(global::PingHandler), global::Microsoft.Extensions.DependencyInjection.ServiceLifetime.Singleton));
            services.Add(new SD(
                typeof(global::Mediator.RequestClassHandlerWrapper<global::Ping, global::Pong>),
                sp =>
                {
                    return new global::Mediator.RequestClassHandlerWrapper<global::Ping, global::Pong>(
                        sp.GetRequiredService<global::PingHandler>(),
                        sp.GetServices<global::Mediator.IPipelineBehavior<global::Ping, global::Pong>>()
                    );
                },
                global::Microsoft.Extensions.DependencyInjection.ServiceLifetime.Singleton
            ));




            services.AddSingleton<Dummy>();

            return services;

        }
    }
}

namespace Mediator
{
    [global::System.CodeDom.Compiler.GeneratedCode("Mediator.SourceGenerator", "2.1.0.0")]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.Diagnostics.DebuggerStepThroughAttribute]
    internal sealed class RequestClassHandlerWrapper<TRequest, TResponse>
        where TRequest : class, global::Mediator.IRequest<TResponse>
    {
        private readonly global::Mediator.MessageHandlerDelegate<TRequest, TResponse> _rootHandler;

        public RequestClassHandlerWrapper(
            global::Mediator.IRequestHandler<TRequest, TResponse> concreteHandler,
            global::System.Collections.Generic.IEnumerable<global::Mediator.IPipelineBehavior<TRequest, TResponse>> pipelineBehaviours
        )
        {
            var handler = (global::Mediator.MessageHandlerDelegate<TRequest, TResponse>)concreteHandler.Handle;

            foreach (var pipeline in pipelineBehaviours.Reverse())
            {
                var handlerCopy = handler;
                var pipelineCopy = pipeline;
                handler = (TRequest message, System.Threading.CancellationToken cancellationToken) => pipelineCopy.Handle(message, cancellationToken, handlerCopy);
            }

            _rootHandler = handler;
        }

        public global::System.Threading.Tasks.ValueTask<TResponse> Handle(TRequest request, global::System.Threading.CancellationToken cancellationToken) =>
            _rootHandler(request, cancellationToken);
    }
    [global::System.CodeDom.Compiler.GeneratedCode("Mediator.SourceGenerator", "2.1.0.0")]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.Diagnostics.DebuggerStepThroughAttribute]
    internal sealed class RequestStructHandlerWrapper<TRequest, TResponse>
        where TRequest : struct, global::Mediator.IRequest<TResponse>
    {
        private readonly global::Mediator.MessageHandlerDelegate<TRequest, TResponse> _rootHandler;

        public RequestStructHandlerWrapper(
            global::Mediator.IRequestHandler<TRequest, TResponse> concreteHandler,
            global::System.Collections.Generic.IEnumerable<global::Mediator.IPipelineBehavior<TRequest, TResponse>> pipelineBehaviours
        )
        {
            var handler = (global::Mediator.MessageHandlerDelegate<TRequest, TResponse>)concreteHandler.Handle;

            foreach (var pipeline in pipelineBehaviours.Reverse())
            {
                var handlerCopy = handler;
                var pipelineCopy = pipeline;
                handler = (TRequest message, System.Threading.CancellationToken cancellationToken) => pipelineCopy.Handle(message, cancellationToken, handlerCopy);
            }

            _rootHandler = handler;
        }

        public global::System.Threading.Tasks.ValueTask<TResponse> Handle(TRequest request, global::System.Threading.CancellationToken cancellationToken) =>
            _rootHandler(request, cancellationToken);
    }
    [global::System.CodeDom.Compiler.GeneratedCode("Mediator.SourceGenerator", "2.1.0.0")]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.Diagnostics.DebuggerStepThroughAttribute]
    internal sealed class StreamRequestClassHandlerWrapper<TRequest, TResponse>
        where TRequest : class, global::Mediator.IStreamRequest<TResponse>
    {
        private readonly global::Mediator.StreamHandlerDelegate<TRequest, TResponse> _rootHandler;

        public StreamRequestClassHandlerWrapper(
            global::Mediator.IStreamRequestHandler<TRequest, TResponse> concreteHandler,
            global::System.Collections.Generic.IEnumerable<global::Mediator.IStreamPipelineBehavior<TRequest, TResponse>> pipelineBehaviours
        )
        {
            var handler = (global::Mediator.StreamHandlerDelegate<TRequest, TResponse>)concreteHandler.Handle;

            foreach (var pipeline in pipelineBehaviours.Reverse())
            {
                var handlerCopy = handler;
                var pipelineCopy = pipeline;
                handler = (TRequest message, System.Threading.CancellationToken cancellationToken) => pipelineCopy.Handle(message, cancellationToken, handlerCopy);
            }

            _rootHandler = handler;
        }

        public global::System.Collections.Generic.IAsyncEnumerable<TResponse> Handle(TRequest request, global::System.Threading.CancellationToken cancellationToken) =>
            _rootHandler(request, cancellationToken);
    }
    [global::System.CodeDom.Compiler.GeneratedCode("Mediator.SourceGenerator", "2.1.0.0")]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.Diagnostics.DebuggerStepThroughAttribute]
    internal sealed class StreamRequestStructHandlerWrapper<TRequest, TResponse>
        where TRequest : struct, global::Mediator.IStreamRequest<TResponse>
    {
        private readonly global::Mediator.StreamHandlerDelegate<TRequest, TResponse> _rootHandler;

        public StreamRequestStructHandlerWrapper(
            global::Mediator.IStreamRequestHandler<TRequest, TResponse> concreteHandler,
            global::System.Collections.Generic.IEnumerable<global::Mediator.IStreamPipelineBehavior<TRequest, TResponse>> pipelineBehaviours
        )
        {
            var handler = (global::Mediator.StreamHandlerDelegate<TRequest, TResponse>)concreteHandler.Handle;

            foreach (var pipeline in pipelineBehaviours.Reverse())
            {
                var handlerCopy = handler;
                var pipelineCopy = pipeline;
                handler = (TRequest message, System.Threading.CancellationToken cancellationToken) => pipelineCopy.Handle(message, cancellationToken, handlerCopy);
            }

            _rootHandler = handler;
        }

        public global::System.Collections.Generic.IAsyncEnumerable<TResponse> Handle(TRequest request, global::System.Threading.CancellationToken cancellationToken) =>
            _rootHandler(request, cancellationToken);
    }
    [global::System.CodeDom.Compiler.GeneratedCode("Mediator.SourceGenerator", "2.1.0.0")]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.Diagnostics.DebuggerStepThroughAttribute]
    internal sealed class CommandClassHandlerWrapper<TRequest, TResponse>
        where TRequest : class, global::Mediator.ICommand<TResponse>
    {
        private readonly global::Mediator.MessageHandlerDelegate<TRequest, TResponse> _rootHandler;

        public CommandClassHandlerWrapper(
            global::Mediator.ICommandHandler<TRequest, TResponse> concreteHandler,
            global::System.Collections.Generic.IEnumerable<global::Mediator.IPipelineBehavior<TRequest, TResponse>> pipelineBehaviours
        )
        {
            var handler = (global::Mediator.MessageHandlerDelegate<TRequest, TResponse>)concreteHandler.Handle;

            foreach (var pipeline in pipelineBehaviours.Reverse())
            {
                var handlerCopy = handler;
                var pipelineCopy = pipeline;
                handler = (TRequest message, System.Threading.CancellationToken cancellationToken) => pipelineCopy.Handle(message, cancellationToken, handlerCopy);
            }

            _rootHandler = handler;
        }

        public global::System.Threading.Tasks.ValueTask<TResponse> Handle(TRequest request, global::System.Threading.CancellationToken cancellationToken) =>
            _rootHandler(request, cancellationToken);
    }
    [global::System.CodeDom.Compiler.GeneratedCode("Mediator.SourceGenerator", "2.1.0.0")]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.Diagnostics.DebuggerStepThroughAttribute]
    internal sealed class CommandStructHandlerWrapper<TRequest, TResponse>
        where TRequest : struct, global::Mediator.ICommand<TResponse>
    {
        private readonly global::Mediator.MessageHandlerDelegate<TRequest, TResponse> _rootHandler;

        public CommandStructHandlerWrapper(
            global::Mediator.ICommandHandler<TRequest, TResponse> concreteHandler,
            global::System.Collections.Generic.IEnumerable<global::Mediator.IPipelineBehavior<TRequest, TResponse>> pipelineBehaviours
        )
        {
            var handler = (global::Mediator.MessageHandlerDelegate<TRequest, TResponse>)concreteHandler.Handle;

            foreach (var pipeline in pipelineBehaviours.Reverse())
            {
                var handlerCopy = handler;
                var pipelineCopy = pipeline;
                handler = (TRequest message, System.Threading.CancellationToken cancellationToken) => pipelineCopy.Handle(message, cancellationToken, handlerCopy);
            }

            _rootHandler = handler;
        }

        public global::System.Threading.Tasks.ValueTask<TResponse> Handle(TRequest request, global::System.Threading.CancellationToken cancellationToken) =>
            _rootHandler(request, cancellationToken);
    }
    [global::System.CodeDom.Compiler.GeneratedCode("Mediator.SourceGenerator", "2.1.0.0")]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.Diagnostics.DebuggerStepThroughAttribute]
    internal sealed class StreamCommandClassHandlerWrapper<TRequest, TResponse>
        where TRequest : class, global::Mediator.IStreamCommand<TResponse>
    {
        private readonly global::Mediator.StreamHandlerDelegate<TRequest, TResponse> _rootHandler;

        public StreamCommandClassHandlerWrapper(
            global::Mediator.IStreamCommandHandler<TRequest, TResponse> concreteHandler,
            global::System.Collections.Generic.IEnumerable<global::Mediator.IStreamPipelineBehavior<TRequest, TResponse>> pipelineBehaviours
        )
        {
            var handler = (global::Mediator.StreamHandlerDelegate<TRequest, TResponse>)concreteHandler.Handle;

            foreach (var pipeline in pipelineBehaviours.Reverse())
            {
                var handlerCopy = handler;
                var pipelineCopy = pipeline;
                handler = (TRequest message, System.Threading.CancellationToken cancellationToken) => pipelineCopy.Handle(message, cancellationToken, handlerCopy);
            }

            _rootHandler = handler;
        }

        public global::System.Collections.Generic.IAsyncEnumerable<TResponse> Handle(TRequest request, global::System.Threading.CancellationToken cancellationToken) =>
            _rootHandler(request, cancellationToken);
    }
    [global::System.CodeDom.Compiler.GeneratedCode("Mediator.SourceGenerator", "2.1.0.0")]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.Diagnostics.DebuggerStepThroughAttribute]
    internal sealed class StreamCommandStructHandlerWrapper<TRequest, TResponse>
        where TRequest : struct, global::Mediator.IStreamCommand<TResponse>
    {
        private readonly global::Mediator.StreamHandlerDelegate<TRequest, TResponse> _rootHandler;

        public StreamCommandStructHandlerWrapper(
            global::Mediator.IStreamCommandHandler<TRequest, TResponse> concreteHandler,
            global::System.Collections.Generic.IEnumerable<global::Mediator.IStreamPipelineBehavior<TRequest, TResponse>> pipelineBehaviours
        )
        {
            var handler = (global::Mediator.StreamHandlerDelegate<TRequest, TResponse>)concreteHandler.Handle;

            foreach (var pipeline in pipelineBehaviours.Reverse())
            {
                var handlerCopy = handler;
                var pipelineCopy = pipeline;
                handler = (TRequest message, System.Threading.CancellationToken cancellationToken) => pipelineCopy.Handle(message, cancellationToken, handlerCopy);
            }

            _rootHandler = handler;
        }

        public global::System.Collections.Generic.IAsyncEnumerable<TResponse> Handle(TRequest request, global::System.Threading.CancellationToken cancellationToken) =>
            _rootHandler(request, cancellationToken);
    }
    [global::System.CodeDom.Compiler.GeneratedCode("Mediator.SourceGenerator", "2.1.0.0")]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.Diagnostics.DebuggerStepThroughAttribute]
    internal sealed class QueryClassHandlerWrapper<TRequest, TResponse>
        where TRequest : class, global::Mediator.IQuery<TResponse>
    {
        private readonly global::Mediator.MessageHandlerDelegate<TRequest, TResponse> _rootHandler;

        public QueryClassHandlerWrapper(
            global::Mediator.IQueryHandler<TRequest, TResponse> concreteHandler,
            global::System.Collections.Generic.IEnumerable<global::Mediator.IPipelineBehavior<TRequest, TResponse>> pipelineBehaviours
        )
        {
            var handler = (global::Mediator.MessageHandlerDelegate<TRequest, TResponse>)concreteHandler.Handle;

            foreach (var pipeline in pipelineBehaviours.Reverse())
            {
                var handlerCopy = handler;
                var pipelineCopy = pipeline;
                handler = (TRequest message, System.Threading.CancellationToken cancellationToken) => pipelineCopy.Handle(message, cancellationToken, handlerCopy);
            }

            _rootHandler = handler;
        }

        public global::System.Threading.Tasks.ValueTask<TResponse> Handle(TRequest request, global::System.Threading.CancellationToken cancellationToken) =>
            _rootHandler(request, cancellationToken);
    }
    [global::System.CodeDom.Compiler.GeneratedCode("Mediator.SourceGenerator", "2.1.0.0")]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.Diagnostics.DebuggerStepThroughAttribute]
    internal sealed class QueryStructHandlerWrapper<TRequest, TResponse>
        where TRequest : struct, global::Mediator.IQuery<TResponse>
    {
        private readonly global::Mediator.MessageHandlerDelegate<TRequest, TResponse> _rootHandler;

        public QueryStructHandlerWrapper(
            global::Mediator.IQueryHandler<TRequest, TResponse> concreteHandler,
            global::System.Collections.Generic.IEnumerable<global::Mediator.IPipelineBehavior<TRequest, TResponse>> pipelineBehaviours
        )
        {
            var handler = (global::Mediator.MessageHandlerDelegate<TRequest, TResponse>)concreteHandler.Handle;

            foreach (var pipeline in pipelineBehaviours.Reverse())
            {
                var handlerCopy = handler;
                var pipelineCopy = pipeline;
                handler = (TRequest message, System.Threading.CancellationToken cancellationToken) => pipelineCopy.Handle(message, cancellationToken, handlerCopy);
            }

            _rootHandler = handler;
        }

        public global::System.Threading.Tasks.ValueTask<TResponse> Handle(TRequest request, global::System.Threading.CancellationToken cancellationToken) =>
            _rootHandler(request, cancellationToken);
    }
    [global::System.CodeDom.Compiler.GeneratedCode("Mediator.SourceGenerator", "2.1.0.0")]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.Diagnostics.DebuggerStepThroughAttribute]
    internal sealed class StreamQueryClassHandlerWrapper<TRequest, TResponse>
        where TRequest : class, global::Mediator.IStreamQuery<TResponse>
    {
        private readonly global::Mediator.StreamHandlerDelegate<TRequest, TResponse> _rootHandler;

        public StreamQueryClassHandlerWrapper(
            global::Mediator.IStreamQueryHandler<TRequest, TResponse> concreteHandler,
            global::System.Collections.Generic.IEnumerable<global::Mediator.IStreamPipelineBehavior<TRequest, TResponse>> pipelineBehaviours
        )
        {
            var handler = (global::Mediator.StreamHandlerDelegate<TRequest, TResponse>)concreteHandler.Handle;

            foreach (var pipeline in pipelineBehaviours.Reverse())
            {
                var handlerCopy = handler;
                var pipelineCopy = pipeline;
                handler = (TRequest message, System.Threading.CancellationToken cancellationToken) => pipelineCopy.Handle(message, cancellationToken, handlerCopy);
            }

            _rootHandler = handler;
        }

        public global::System.Collections.Generic.IAsyncEnumerable<TResponse> Handle(TRequest request, global::System.Threading.CancellationToken cancellationToken) =>
            _rootHandler(request, cancellationToken);
    }
    [global::System.CodeDom.Compiler.GeneratedCode("Mediator.SourceGenerator", "2.1.0.0")]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.Diagnostics.DebuggerStepThroughAttribute]
    internal sealed class StreamQueryStructHandlerWrapper<TRequest, TResponse>
        where TRequest : struct, global::Mediator.IStreamQuery<TResponse>
    {
        private readonly global::Mediator.StreamHandlerDelegate<TRequest, TResponse> _rootHandler;

        public StreamQueryStructHandlerWrapper(
            global::Mediator.IStreamQueryHandler<TRequest, TResponse> concreteHandler,
            global::System.Collections.Generic.IEnumerable<global::Mediator.IStreamPipelineBehavior<TRequest, TResponse>> pipelineBehaviours
        )
        {
            var handler = (global::Mediator.StreamHandlerDelegate<TRequest, TResponse>)concreteHandler.Handle;

            foreach (var pipeline in pipelineBehaviours.Reverse())
            {
                var handlerCopy = handler;
                var pipelineCopy = pipeline;
                handler = (TRequest message, System.Threading.CancellationToken cancellationToken) => pipelineCopy.Handle(message, cancellationToken, handlerCopy);
            }

            _rootHandler = handler;
        }

        public global::System.Collections.Generic.IAsyncEnumerable<TResponse> Handle(TRequest request, global::System.Threading.CancellationToken cancellationToken) =>
            _rootHandler(request, cancellationToken);
    }

    /// <summary>
    /// Generated code for Mediator implementation.
    /// This type is also registered as a DI service.
    /// Can be used directly for high performance scenarios.
    /// </summary>
    [global::System.CodeDom.Compiler.GeneratedCode("Mediator.SourceGenerator", "2.1.0.0")]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.Diagnostics.DebuggerStepThroughAttribute]
    public sealed partial class Mediator : global::Mediator.IMediator, global::Mediator.ISender, global::Mediator.IPublisher
    {
        private readonly global::System.IServiceProvider _sp;
        private FastLazyValue<DICache> _diCacheLazy;

        /// <summary>
        /// The lifetime of Mediator-related service registrations in DI container.
        /// </summary>
        public static global::Microsoft.Extensions.DependencyInjection.ServiceLifetime ServiceLifetime { get; } = global::Microsoft.Extensions.DependencyInjection.ServiceLifetime.Singleton;

        private readonly global::System.Func<global::System.Collections.Generic.IEnumerable<object>, int> _getServicesLength;

        /// <summary>
        /// Constructor for DI, should not be used by consumer.
        /// </summary>
        public Mediator(global::System.IServiceProvider sp)
        {
            _sp = sp;
            _diCacheLazy = new FastLazyValue<DICache>(() => new DICache(_sp));

            global::System.Func<global::System.Collections.Generic.IEnumerable<object>, int> fastGetLength = s => ((object[])s).Length;
            global::System.Func<global::System.Collections.Generic.IEnumerable<object>, int> slowGetLength = s => s.Count();

            var dummy = sp.GetServices<global::Microsoft.Extensions.DependencyInjection.MediatorDependencyInjectionExtensions.Dummy>();
            _getServicesLength = dummy.GetType() == typeof(global::Microsoft.Extensions.DependencyInjection.MediatorDependencyInjectionExtensions.Dummy[])
                 ? fastGetLength : slowGetLength;
        }

        private struct FastLazyValue<T>
            where T : struct
        {
            private const long UNINIT = 0;
            private const long INITING = 1;
            private const long INITD = 2;
            
            

            private global::System.Func<T> _generator;
            private long _state;
            private T _value;

            public T Value
            {
                [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
                get
                {
                    if (_state != INITD)
                        return ValueSlow;

                    return _value;
                }
            }

            private T ValueSlow
            {
                [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
                get
                {
                    var prevState = global::System.Threading.Interlocked.CompareExchange(ref _state, INITING, UNINIT);
                    switch (prevState)
                    {
                        case INITD:
                            // Someone has already completed init
                            return _value;
                        case INITING:
                            // Wait for someone else to complete
                            var spinWait = default(global::System.Threading.SpinWait);
                            while (global::System.Threading.Interlocked.Read(ref _state) < INITD)
                                spinWait.SpinOnce();
                            return _value;
                        case UNINIT:
                            _value = _generator();
                            global::System.Threading.Interlocked.Exchange(ref _state, INITD);
                            return _value;
                    }

                    return _value;
                }
            }


            public FastLazyValue(global::System.Func<T> generator)
            {
                _generator = generator;
                _state = UNINIT;
                _value = default;
            }
        }

                private readonly struct DICache
        {
            private readonly global::System.IServiceProvider _sp;

            public readonly global::Mediator.RequestClassHandlerWrapper<global::Ping, global::Pong> Wrapper_For_Ping;

            public DICache(global::System.IServiceProvider sp)
            {
                _sp = sp;

                Wrapper_For_Ping = sp.GetRequiredService<global::Mediator.RequestClassHandlerWrapper<global::Ping, global::Pong>>();
            }
        }

        /// <summary>
        /// Send a message of type global::Ping.
        /// Throws <see cref="global::System.ArgumentNullException"/> if message is null.
        /// </summary>
        /// <param name="message">Incoming message</param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <returns>Awaitable task</returns>
        public global::System.Threading.Tasks.ValueTask<global::Pong> Send(
            global::Ping message,
            global::System.Threading.CancellationToken cancellationToken = default
        )
        {
            ThrowIfNull(message, nameof(message));
            
            return _diCacheLazy.Value.Wrapper_For_Ping.Handle(message, cancellationToken);
        }

        /// <summary>
        /// Send request.
        /// Throws <see cref="global::System.ArgumentNullException"/> if message is null.
        /// Throws <see cref="global::Mediator.MissingMessageHandlerException"/> if no handler is registered.
        /// </summary>
        /// <param name="request">Incoming request</param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <returns>Awaitable task</returns>
        public global::System.Threading.Tasks.ValueTask<TResponse> Send<TResponse>(
            global::Mediator.IRequest<TResponse> request,
            global::System.Threading.CancellationToken cancellationToken = default
        )
        {
            switch (request)
            {
                case global::Ping r:
                {
                    if(typeof(TResponse) == typeof(global::Pong))
                    {
                        var task = Send(r, cancellationToken);
                        return global::System.Runtime.CompilerServices.Unsafe.As<global::System.Threading.Tasks.ValueTask<global::Pong>, global::System.Threading.Tasks.ValueTask<TResponse>>(ref task);
                    }
                    else
                    {
                        return SendAsync(request, cancellationToken);
                    }
                }
                default:
                {
                    ThrowArgumentNullOrInvalidMessage(request, nameof(request));
                    return default;
                }
            }
            
        }

        /// <summary>
        /// Send request.
        /// Throws <see cref="global::System.ArgumentNullException"/> if message is null.
        /// Throws <see cref="global::Mediator.MissingMessageHandlerException"/> if no handler is registered.
        /// </summary>
        /// <param name="request">Incoming request</param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <returns>Awaitable task</returns>
        private async global::System.Threading.Tasks.ValueTask<TResponse> SendAsync<TResponse>(
            global::Mediator.IRequest<TResponse> request,
            global::System.Threading.CancellationToken cancellationToken = default
        )
        {
            switch (request)
            {
                case global::Ping r:
                {
                    var response = await Send(r, cancellationToken);
                    return global::System.Runtime.CompilerServices.Unsafe.As<global::Pong, TResponse>(ref response);
                }
                default:
                {
                    ThrowArgumentNullOrInvalidMessage(request, nameof(request));
                    return default;
                }
            }
            
        }

        /// <summary>
        /// Create stream for request.
        /// Throws <see cref="global::System.ArgumentNullException"/> if message is null.
        /// Throws <see cref="global::Mediator.MissingMessageHandlerException"/> if no handler is registered.
        /// </summary>
        /// <param name="request">Incoming message</param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <returns>Async enumerable</returns>
        public global::System.Collections.Generic.IAsyncEnumerable<TResponse> CreateStream<TResponse>(
            global::Mediator.IStreamRequest<TResponse> request,
            global::System.Threading.CancellationToken cancellationToken = default
        )
        {
            ThrowInvalidMessage(request);
            return default;
            
        }

        /// <summary>
        /// Send command.
        /// Throws <see cref="global::System.ArgumentNullException"/> if message is null.
        /// Throws <see cref="global::Mediator.MissingMessageHandlerException"/> if no handler is registered.
        /// </summary>
        /// <param name="command">Incoming command</param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <returns>Awaitable task</returns>
        public global::System.Threading.Tasks.ValueTask<TResponse> Send<TResponse>(
            global::Mediator.ICommand<TResponse> command,
            global::System.Threading.CancellationToken cancellationToken = default
        )
        {
            ThrowInvalidMessage(command);
            return default;
            
        }

        /// <summary>
        /// Send command.
        /// Throws <see cref="global::System.ArgumentNullException"/> if message is null.
        /// Throws <see cref="global::Mediator.MissingMessageHandlerException"/> if no handler is registered.
        /// </summary>
        /// <param name="command">Incoming command</param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <returns>Awaitable task</returns>
        private async global::System.Threading.Tasks.ValueTask<TResponse> SendAsync<TResponse>(
            global::Mediator.ICommand<TResponse> command,
            global::System.Threading.CancellationToken cancellationToken = default
        )
        {
            ThrowInvalidMessage(command);
            return default;
            
        }

        /// <summary>
        /// Create stream for command.
        /// Throws <see cref="global::System.ArgumentNullException"/> if message is null.
        /// Throws <see cref="global::Mediator.MissingMessageHandlerException"/> if no handler is registered.
        /// </summary>
        /// <param name="command">Incoming message</param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <returns>Async enumerable</returns>
        public global::System.Collections.Generic.IAsyncEnumerable<TResponse> CreateStream<TResponse>(
            global::Mediator.IStreamCommand<TResponse> command,
            global::System.Threading.CancellationToken cancellationToken = default
        )
        {
            ThrowInvalidMessage(command);
            return default;
            
        }

        /// <summary>
        /// Send query.
        /// Throws <see cref="global::System.ArgumentNullException"/> if message is null.
        /// Throws <see cref="global::Mediator.MissingMessageHandlerException"/> if no handler is registered.
        /// </summary>
        /// <param name="query">Incoming query</param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <returns>Awaitable task</returns>
        public global::System.Threading.Tasks.ValueTask<TResponse> Send<TResponse>(
            global::Mediator.IQuery<TResponse> query,
            global::System.Threading.CancellationToken cancellationToken = default
        )
        {
            ThrowInvalidMessage(query);
            return default;
            
        }

        /// <summary>
        /// Send query.
        /// Throws <see cref="global::System.ArgumentNullException"/> if message is null.
        /// Throws <see cref="global::Mediator.MissingMessageHandlerException"/> if no handler is registered.
        /// </summary>
        /// <param name="query">Incoming query</param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <returns>Awaitable task</returns>
        private async global::System.Threading.Tasks.ValueTask<TResponse> SendAsync<TResponse>(
            global::Mediator.IQuery<TResponse> query,
            global::System.Threading.CancellationToken cancellationToken = default
        )
        {
            ThrowInvalidMessage(query);
            return default;
            
        }

        /// <summary>
        /// Create stream for query.
        /// Throws <see cref="global::System.ArgumentNullException"/> if message is null.
        /// Throws <see cref="global::Mediator.MissingMessageHandlerException"/> if no handler is registered.
        /// </summary>
        /// <param name="query">Incoming message</param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <returns>Async enumerable</returns>
        public global::System.Collections.Generic.IAsyncEnumerable<TResponse> CreateStream<TResponse>(
            global::Mediator.IStreamQuery<TResponse> query,
            global::System.Threading.CancellationToken cancellationToken = default
        )
        {
            ThrowInvalidMessage(query);
            return default;
            
        }

        /// <summary>
        /// Send message.
        /// Throws <see cref="global::System.ArgumentNullException"/> if message is null.
        /// Throws <see cref="global::Mediator.MissingMessageHandlerException"/> if no handler is registered.
        /// </summary>
        /// <param name="message">Incoming message</param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <returns>Awaitable task</returns>
        public async global::System.Threading.Tasks.ValueTask<object> Send(
            object message,
            global::System.Threading.CancellationToken cancellationToken = default
        )
        {
            switch (message)
            {
                case global::Ping m: return await Send(m, cancellationToken);
                default:
                {
                    ThrowArgumentNullOrInvalidMessage(message as global::Mediator.IMessage, nameof(message));
                    return default;
                }
            }
            
        }

        /// <summary>
        /// Create stream.
        /// Throws <see cref="global::System.ArgumentNullException"/> if message is null.
        /// Throws <see cref="global::Mediator.MissingMessageHandlerException"/> if no handler is registered.
        /// </summary>
        /// <param name="message">Incoming message</param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <returns>Async enumerable</returns>
        public global::System.Collections.Generic.IAsyncEnumerable<object> CreateStream(
            object message,
            global::System.Threading.CancellationToken cancellationToken = default
        )
        {
            ThrowInvalidMessage(message as global::Mediator.IStreamMessage);
            return default;
            
        }

        /// <summary>
        /// Publish notification.
        /// Throws <see cref="global::System.ArgumentNullException"/> if message is null.
        /// </summary>
        /// <param name="notification">Incoming notification</param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <returns>Awaitable task</returns>
        public global::System.Threading.Tasks.ValueTask Publish(
            object notification,
            global::System.Threading.CancellationToken cancellationToken = default
        )
        {
            return default;
            
        }


        /// <summary>
        /// Publish notification.
        /// Throws <see cref="global::System.ArgumentNullException"/> if message is null.
        /// </summary>
        /// <param name="notification">Incoming notification</param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <returns>Awaitable task</returns>
        public global::System.Threading.Tasks.ValueTask Publish<TNotification>(
            TNotification notification,
            global::System.Threading.CancellationToken cancellationToken = default
        )
            where TNotification : global::Mediator.INotification
        {
            return default;
            
        }

        [global::System.Diagnostics.CodeAnalysis.DoesNotReturn]
        private static void ThrowInvalidMessage(object msg) =>
            throw new global::Mediator.MissingMessageHandlerException(msg);

        [global::System.Diagnostics.CodeAnalysis.DoesNotReturn]
        private static void ThrowArgumentNull(string paramName) =>
            throw new global::System.ArgumentNullException(paramName);

        private static void ThrowIfNull<T>(T argument, string paramName)
        {
            if (argument is null)
            {
                ThrowArgumentNull(paramName);
            }
        }

        [global::System.Diagnostics.CodeAnalysis.DoesNotReturn]
        private static void ThrowArgumentNullOrInvalidMessage(object msg, string paramName)
        {
            if (msg is null)
            {
                ThrowArgumentNull(paramName);
            }
            else
            {
                ThrowInvalidMessage(msg);
            }
        }

        [global::System.Diagnostics.CodeAnalysis.DoesNotReturn]
        private static void ThrowAggregateException(global::System.Collections.Generic.List<global::System.Exception> exceptions) =>
            throw new global::System.AggregateException(exceptions);

        private static void MaybeThrowAggregateException(global::System.Collections.Generic.List<global::System.Exception> exceptions)
        {
            if (exceptions != null)
            {
                ThrowAggregateException(exceptions);
            }
        }
    }
}

// <auto-generated>
//     Generated by the Mediator source generator.
// </auto-generated>

namespace Mediator
{
    /// <summary>
    /// Provide options for the Mediator source generator.
    /// </summary>
    [global::System.CodeDom.Compiler.GeneratedCode("Mediator.SourceGenerator", "2.1.0.0")]
    public sealed class MediatorOptions
    {
        /// <summary>
        /// The namespace in which the Mediator implementation is generated.
        /// </summary>
        public string Namespace { get; set; } = "Mediator";

        /// <summary>
        /// The default lifetime of the services registered in the DI container by
        /// the Mediator source generator.
        /// Singleton by default.
        /// </summary>
        public global::Microsoft.Extensions.DependencyInjection.ServiceLifetime ServiceLifetime { get; set; } =
            global::Microsoft.Extensions.DependencyInjection.ServiceLifetime.Singleton;
    }
}

// <auto-generated>
//     Generated by the Mediator source generator.
// </auto-generated>

namespace Mediator
{
    /// <summary>
    /// Provide options for the Mediator source generator.
    /// </summary>
    [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, AllowMultiple = false)]
    [global::System.CodeDom.Compiler.GeneratedCode("Mediator.SourceGenerator", "2.1.0.0")]
    public sealed class MediatorOptionsAttribute : global::System.Attribute
    {
        /// <summary>
        /// The namespace in which the Mediator implementation is generated.
        /// </summary>
        public string Namespace { get; set; } = "Mediator";

        /// <summary>
        /// The default lifetime of the services registered in the DI container by
        /// the Mediator source generator.
        /// Singleton by default.
        /// </summary>
        public global::Microsoft.Extensions.DependencyInjection.ServiceLifetime ServiceLifetime { get; set; } =
            global::Microsoft.Extensions.DependencyInjection.ServiceLifetime.Singleton;
    }
}

Code and pdf at

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