MediatR - 1.0


Extension ID

com.castsoftware.dotnet.mediatr

What’s new?

See Release Notes for more information.

Description

This extension provides support for MediatR for .NET APIs which are responsible for publishing and receiving messages across messaging queues.

In what situation should you install this extension?

If your C# application utilizes MediatR for messaging and you want to view a model that shows the message publisher and handler objects with their corresponding links, then you should install this extension.

Technology support

The following libraries are supported by this extension:

Language Library name Namespace Version Supported
C# MediatRexternal link MediatR 0.1.0 to 12.3.0
C# Mediator.Abstractionsexternal link Mediator 1.0.5 to 2.1.7

Function Point, Quality and Sizing support

  • Function Points (transactions): a green tick indicates that OMG Function Point counting and Transaction Risk Index are supported
  • Quality and Sizing: a green tick indicates that CAST can measure size and that a minimum set of Quality Rules exist
Function Points (transactions) Quality and Sizing

Compatibility

Core release Operating System Supported
8.4.x Microsoft Windows / Linux
8.3.x Microsoft Windows

Dependencies

The MediatR extension is dependent on following extensions:

  • Internal extension (com.castsoftware.internal.platform)

Download and installation instructions

The extension will not be automatically downloaded and installed. If you need to use it, you should manually install it.

What results can you expect?

Once the analysis/snapshot generation has completed, you can view the below objects and links created.

Objects

Icon Description Comment
MediatR DotNet Publisher an object is created for each message published and message type is resolved
MediatR DotNet Handler an object is created for each resolved Message Handler
MediatR Unknown DotNet Publisher an object is created for each message published and message type is not resolved in a method call
Link Type Source and Destination Link Supported APIs
callLink Link between the caller C# method and the DotNet MediatR Publisher object
MediatR Publisher APIsMediatR.IMediator.Publish
MediatR.IMediator.PublishAsync
MediatR.IMediator.Send
MediatR.IMediator.SendAsync
MediatR.IMediator.Stream
MediatR.IMediator.CreateStream
MediatR.ISender.Send
MediatR.ISender.CreateStream
MediatR.IPublisher.Publish
MediatR.Mediator.Publish
MediatR.Mediator.Send

Mediator Publisher APIsMediator.IPublisher.Publish
Mediator.ISender.Send
Mediator.ISender.CreateStream
callLink Link between the DotNet MediatR Handler object and the caller C# method
MediatR Handler APIs
MediatR.IRequestHandler
MediatR.INotificationHandler
MediatR.IStreamRequestHandler
MediatR.IAsyncNotificationHandler
MediatR.IAsyncRequestHandler
MediatR.IAsyncRequestStreamHandler

Mediator Handler APIsMediator.ICommandHandler
Mediator.INotificationHandler
Mediator.IQueryHandler
Mediator.IRequestHandler
Mediator.IStreamCommandHandler
Mediator.IStreamQueryHandler
Mediator.IStreamRequestHandler

Code Examples

Publisher

Publish

using MediatR;
using Microsoft.Extensions.DependencyInjection;

public class Benchmarks
{
    private IMediator _mediator;
    private readonly Pinged _notification = new Pinged();

    public void GlobalSetup()
    {
        var services = new ServiceCollection();
        services.AddMediatR(cfg =>
        {
            cfg.RegisterServicesFromAssemblyContaining(typeof(Ping));
        });
        var provider = services.BuildServiceProvider();
        _mediator = provider.GetRequiredService<IMediator>();
    }

    public Task PublishingNotifications()
    {
        return _mediator.Publish(_notification);
    }
}

Send


private static async Task<bool> IsHandlerForLessSpecificExceptionWorks(IMediator mediator, WrappingWriter writer)
    {
        var isHandledCorrectly = false;

        await writer.WriteLineAsync("Checking base handler to catch any exception...");
        try
        {
            await mediator.Send(new PingResourceTimeout { Message = "Ping to ISS resource" });
            isHandledCorrectly = IsExceptionHandledBy<TaskCanceledException, CommonExceptionHandler> (writer);
        }
        catch (Exception e)
        {
            await writer.WriteLineAsync(e.Message);
        }
        await writer.WriteLineAsync();

        return isHandledCorrectly;
    }

CreateStream

public async Task Should_register_and_wrap_with_behavior()
    {
        var output = new Logger();
        IServiceCollection services = new ServiceCollection();
        services.AddSingleton(output);
        services.AddMediatR(cfg =>
        {
            cfg.RegisterServicesFromAssembly(typeof(Ping).Assembly);
            cfg.
        });
        var provider = services.BuildServiceProvider();

        var mediator = provider.GetRequiredService<IMediator>();

        var stream = mediator.CreateStream(new StreamPing { Message = "Ping" });

        await foreach (var response in stream)
        {
            response.Message.ShouldBe("Ping Pang");
        }
    }

Unknown Publisher

MediatR Unknown DotNet Publihser object is created where the message type that is being sent cannot be resolved

public Task Should_raise_execption_on_null_request() => Should.ThrowAsync<ArgumentNullException>(async () => await _mediator.Send(default!));

Handlers

NotificationHandler

public class PingedHandler : INotificationHandler<Pinged>
{
    public Task Handle(Pinged notification, CancellationToken cancellationToken)
    {
        return Task.CompletedTask;
    }
}

RequestHandler

public class PingResourceTimeoutHandler : IRequestHandler<PingResourceTimeout, Pong>
{
    private readonly TextWriter _writer;

    public PingResourceTimeoutHandler(TextWriter writer) => _writer = writer;

    public Task<Pong> Handle(PingResourceTimeout request, CancellationToken cancellationToken)
    {
        throw new TaskCanceledException();
    }
}

StreamRequestHandler

public class PingStreamHandler : IStreamRequestHandler<StreamPing, Pong>
    {
        private readonly Logger _output;

        public PingStreamHandler(Logger output)
        {
            _output = output;
        }
        public async IAsyncEnumerable<Pong> Handle(StreamPing request, [EnumeratorCancellation] CancellationToken cancellationToken)
        {
            _output.Messages.Add("Handler");
            yield return await Task.Run(() => new Pong { Message = request.Message + " Pang" }, cancellationToken);
        }
    }