I'm currently revamping some large controllers in our asp.net core app. To do so we chose Mediatr and we are currently splitting those big actions into handlers & pre/post processors.
Some of our commands need to trigger an internal notification system (node.js service). To do so, I have developed a post processor in charge of notifying the event service. However, I want to "trigger" it only for commands inheriting from the INotify
interface. In other words, Mediatr loads all pre/post processors but it triggers only those whose command type is matching the generic constraint. In the end it would look like this:
public class NotificationPostProcessor<TCommand, TResponse> : IRequestPostProcessor<TCommand, TResponse>
where TCommand : >>INotifyCommand<<
where TResponse : CommandResult
{
(...)
}
If the command does not inherit from INotifyCommand then this post-processor is not triggered.
Same thing goes for pre-processors. For example, I would need my pre-processor to add some extra data to some specific command.
Currently what I do is horrible and I'm sure there is a better way.
public class NotificationPostProcessor<TCommand, TResponse> : IRequestPostProcessor<TCommand, TResponse>
where TCommand : IRequest<TResponse>
where TResponse : CommandResult
{
private readonly INotificationService _service;
public NotificationPostProcessor(INotificationService service)
{
_service = service;
}
public async Task Process(TCommand command, TResponse response)
{
var cmd = command as NotifyBaseCommand;
if (cmd != null && response.IsSuccess)
await _service.Notify(cmd.Event, command, response);
}
}
Since I'm using the default asp.net core dependency injection engine + MediatR.Extensions.Microsoft.DependencyInjection
package, I'm not directly registering Post & Pre processors.
// Pipeline engine used internally to simplify controllers
services.AddMediatR();
// Registers behaviors
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(Pipeline<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(AuditBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestPreProcessorBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestPostProcessorBehavior<,>));
// Registers command validator
services.AddTransient(typeof(IValidator<RegisterUserCommand>), typeof(RegisterUserCommandValidator));
I'm must admit I'm a little bit lost here. Any idea on how i can improve this system?
Thank you, Sebastien
Apparently ASP.net core DI does not support this feature.
SRC: Support constrained open generic types
It worked with Autofac. I just had to add one single line of code :)
var host = new WebHostBuilder()
.UseKestrel()
.ConfigureServices(services => services.AddAutofac())
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.UseApplicationInsights()
.Build();