MediatR - 1.1
Extension ID
com.castsoftware.dotnet.mediatr
What’s new?
See MediatR for .NET - 1.1 - Release Notes for more information.
Description
This extension provides support for libraries such as MediatR, Mediator.Abstractions, FluentMediator, which implement the Mediator design pattern on .NET
In what situation should you install this extension?
If your .NET application uses Mediator design pattern for messaging and you want to view a model that shows the transaction between the message publisher and handler object with their corresponding links
Technology support
The following libraries are supported by this extension:
Language | Library name | Namespace | Version | Supported |
---|---|---|---|---|
.NET | MediatR | MediatR | 0.1.0 to 12.3.0 | ✅ |
.NET | Mediator.Abstractions | Mediator | 1.0.5 to 2.1.7 | ✅ |
.NET | FluentMediator | FluentMediator | 0.0.1 to 0.4.7 | ✅ |
.NET | Mediator.Net | Mediator.Net | 1.0.0 to 4.8.0 | ✅ |
.NET | Elsa.Mediator | Elsa.Mediator | 3.0.0 to 3.2.3 | ✅ |
.NET | Handyman.Mediator | Handyman.Mediator | 1.0.0 to 12.0.0 | ✅ |
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:
- CAST AIP Internal extension (com.castsoftware.internal.platform)
Download and installation instructions
The extension will not be automatically downloaded and installed in CAST Console. If you need to use it, you should manually install the extension using the Application - Extensions interface:
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 Types
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.PublishMediatR.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 Abstractions Publisher APIsMediator.IPublisher.PublishMediator.ISender.Send Mediator.ISender.CreateStream FluentMediator Publisher APIsFluentMediator.Pipelines.PipelineAsync.IAsyncMediator.PublishAsyncFluentMediator.Pipelines.CancellablePipelineAsync.ICancellablePipelineAsync.PublishAsync FluentMediator.Pipelines.PipelineAsync.IPipelineAsync.PublishAsync FluentMediator.Pipelines.CancellablePipelineAsync.ICancellableMediator.PublishAsync FluentMediator.Pipelines.Pipeline.ISyncMediator.Publish FluentMediator.Pipelines.PipelineAsync.IPipelineAsync.SendAsync FluentMediator.Pipelines.Pipeline.IPipeline.Publish FluentMediator.Pipelines.PipelineAsync.IAsyncMediator.SendAsync FluentMediator.Pipelines.CancellablePipelineAsync.ICancellablePipelineAsync.SendAsync FluentMediator.Pipelines.CancellablePipelineAsync.ICancellableMediator.SendAsync FluentMediator.Pipelines.Pipeline.ISyncMediator.Send FluentMediator.Pipelines.Pipeline.IPipeline.Send Mediator.Net Publisher APIsMediator.Net.IMediator.SendAsyncMediator.Net.IMediator.PublishAsync Mediator.Net.IMediator.RequestAsync Mediator.Net.IMediator.CreateStream Elsa Mediator Publisher APIsElsa.Mediator.Contracts.ICommandSender.SendAsyncElsa.Mediator.Contracts.INotificationSender.SendAsync Elsa.Mediator.Contracts.IRequestSender.SendAsync Handyman.Mediator Publisher APIsHandyman.Mediator.IPublisher.PublishHandyman.Mediator.ISender.Send Handyman.Mediator.IMediator.Send Handyman.Mediator.IMediator.Publish Handyman.Mediator.IDynamicMediator.Publish Handyman.Mediator.IDynamicMediator.Send Handyman.Mediator.IDynamicPublisher.Publish Handyman.Mediator.IDynamicSender.Send |
callLink | Link between the DotNet MediatR Handler object and the caller C# method | MediatR Handler APIsMediatR.IRequestHandlerMediatR.INotificationHandler MediatR.IStreamRequestHandler MediatR.IAsyncNotificationHandler MediatR.IAsyncRequestHandler MediatR.IAsyncRequestStreamHandler Mediator Abstractions Handler APIsMediator.ICommandHandlerMediator.INotificationHandler Mediator.IQueryHandler Mediator.IRequestHandler Mediator.IStreamCommandHandler Mediator.IStreamQueryHandler Mediator.IStreamRequestHandler FluentMediator Handler APIsFluentMediator.Pipelines.PipelineAsync.IPipelineAsyncBuilder.CallFluentMediator.Pipelines.PipelineAsync.IPipelineAsyncBuilder.Return FluentMediator.Pipelines.CancellablePipelineAsync.ICancellablePipelineAsyncBuilder.Call FluentMediator.Pipelines.CancellablePipelineAsync.ICancellablePipelineAsyncBuilder.Return FluentMediator.Pipelines.Pipeline.IPipelineBuilder.Call FluentMediator.Pipelines.Pipeline.IPipelineBuilder.Return Mediator.Net Handler APIsMediator.Net.Contracts.ICommandHandlerMediator.Net.Contracts.IStreamRequestHandler Mediator.Net.Contracts.IEventHandler Mediator.Net.Contracts.IRequestHandler Mediator.Net.Contracts.IStreamCommandHandler Elsa Mediator Handler APIsElsa.Mediator.Contracts.ICommandHandlerElsa.Mediator.Contracts.INotificationHandler Elsa.Mediator.Contracts.IRequestHandler Handyman.Mediator Handler APIsHandyman.Mediator.IEventHandlerHandyman.Mediator.IRequestHandler |
Code Examples
Publisher
MediatR 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);
}
}
MediatR 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;
}
MediatR 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!));
FluentMediator
using FluentMediator;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class TaskService : ITaskService
{
private readonly ITaskRepository _taskRepository;
private readonly ITaskFactory _taskFactory;
private readonly TaskViewModelMapper _taskViewModelMapper;
private readonly ITracer _tracer;
private readonly IMediator _mediator;
public TaskService(ITaskRepository taskRepository, TaskViewModelMapper taskViewModelMapper, ITracer tracer, ITaskFactory taskFactory, IMediator mediator)
{
_taskRepository = taskRepository;
_taskViewModelMapper = taskViewModelMapper;
_tracer = tracer;
_taskFactory = taskFactory;
_mediator = mediator;
}
public async System.Threading.Tasks.Task Delete(Guid id)
{
using (var scope = _tracer.BuildSpan("Delete_TaskService").StartActive(true))
{
var deleteTaskCommand = _taskViewModelMapper.ConvertToDeleteTaskCommand(id);
await _mediator.PublishAsync(deleteTaskCommand);
}
}
}
Mediator.Net
using System;
using System.Threading.Tasks;
using Mediator.Net
using Microsoft.AspNetCore.Mvc;
[Route("api/[controller]")]
public class ValuesController : Controller
{
private readonly IMediator _mediator;
public ValuesController(IMediator mediator)
{
_mediator = mediator;
}
[HttpPost]
[Route(("event"))]
public async Task PostEvent(int id, [FromBody]EventData value)
{
await _mediator.PublishAsync(new ResultCalculatedEvent(value.Result));
}
}
Handyman.Mediator
using Handyman.Mediator;
using Microsoft.Extensions.DependencyInjection;
public class PublisherSample : Sample
{
public override async Task RunAsync(CancellationToken cancellationToken)
{
var mediator = ServiceProvider.GetRequiredService<IPublisher<Event>>();
var @event = new Event();
await mediator.Publish(@event, cancellationToken);
}
}
Handlers
MediatR NotificationHandler
using MediatR;
public class PingedHandler : INotificationHandler<Pinged>
{
public Task Handle(Pinged notification, CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
MediatR RequestHandler
using MediatR;
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();
}
}
MediatR StreamRequestHandler
using MediatR;
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);
}
}
FluentMediator Handler
using System;
using System.Collections.Generic;
using FluentMediator;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddScoped<TaskCommandHandler>();
services.AddScoped<TaskEventHandler>();
services.AddFluentMediator(builder =>
{
builder.On<CreateNewTaskCommand>().PipelineAsync().Return<Domain.Tasks.Task, TaskCommandHandler>((handler, request) => handler.HandleNewTask(request));
builder.On<TaskCreatedEvent>().PipelineAsync().Call<TaskEventHandler>((handler, request) => handler.HandleTaskCreatedEvent(request));
builder.On<DeleteTaskCommand>().PipelineAsync().Call<TaskCommandHandler>((handler, request) => handler.HandleDeleteTask(request));
builder.On<TaskDeletedEvent>().PipelineAsync().Call<TaskEventHandler>((handler, request) => handler.HandleTaskDeletedEvent(request));
});
}
}
Mediator.Net.Contracts Handler
using Mediator.Net.Context;
using Mediator.Net.Contracts;
using Mediator.Net.WebApiSample.Handlers.CommandHandler;
namespace Mediator.Net.WebApiSample.Handlers.EventHandler
{
public class ResultCalculatedEventHandler: IEventHandler<ResultCalculatedEvent>
{
private readonly IBoardcastService _boardcastService;
public ResultCalculatedEventHandler(IBoardcastService boardcastService)
{
_boardcastService = boardcastService;
}
public Task Handle(IReceiveContext<ResultCalculatedEvent> context, CancellationToken cancellationToken)
{
_boardcastService.Boardcast(context.Message.Result);
return Task.FromResult(0);
}
}
}
Handyman.Mediator Handler
using Handyman.Mediator;
using Microsoft.Extensions.DependencyInjection;
public class Handler : IEventHandler<Event>
{
public async Task Handle(Event @event, CancellationToken cancellationToken)
{
await Task.Yield();
Console.WriteLine(GetType().Name);
}
}