Search code examples
c#asp.net-coreautofaccqrsmediatr

Component registration issue using MediatR and Autofac


I'm building a CQRS based .Net Core 2.1 application using Autofac and MediatR.

public class MediatorModule : Autofac.Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterAssemblyTypes(typeof(IMediator).GetTypeInfo().Assembly).AsImplementedInterfaces();

        var mediatrOpenTypes = new[]
        {
            typeof(IRequestHandler<,>),
            typeof(INotificationHandler<>),
        };

        foreach (var mediatrOpenType in mediatrOpenTypes)
        {
            builder
                .RegisterAssemblyTypes(typeof(CreateMessageCommand.GetTypeInfo().Assembly)
                .AsClosedTypesOf(mediatrOpenType)
                .AsImplementedInterfaces();
        }

        builder.RegisterGeneric(typeof(RequestPostProcessorBehavior<,>)).As(typeof(IPipelineBehavior<,>));
        builder.RegisterGeneric(typeof(RequestPreProcessorBehavior<,>)).As(typeof(IPipelineBehavior<,>));

        builder.Register<ServiceFactory>(ctx =>
        {
            var c = ctx.Resolve<IComponentContext>();
            return t => c.Resolve(t);
        });

    }
}

When i feed the command to mediator, it works perfectly fine and the Handle() on the command handler gets executed.

var cmd = new CreateMessageCommand("Foo")
_mediator.Send(cmd)

Things don't go well when i execute it this way

var cmd = new CreateMessageCommand("Foo")
var req = new IdentifiedCommand<CreateMessageCommand, bool>(cmd, @event.Id);
await _mediator.Send(req);

Exception:

Unhandled Exception: System.InvalidOperationException: Error constructing handler for request of type MediatR.IRequestHandler2[Backend.MessageService.Commands.IdentifiedCommand2[Backend.MessageService.Commands.CreateMessageCommand,System.Boolean],System.Boolean]. Register your handlers with the container. See the samples in GitHub for examples. ---> Autofac.Core.Registration.ComponentNotRegisteredException: The requested service 'MediatR.IRequestHandler2[[Backend.MessageService.Commands.IdentifiedCommand2[[Backend.MessageService.Commands.CreateMessageCommand, Backend.MessageService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], Backend.MessageService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.

public class IdentifiedCommand<T, R> : IRequest<R>
    where T : IRequest<R>
{
    public T Command { get; }
    public Guid Id { get; }
    public IdentifiedCommand(T command, Guid id)
    {
        Command = command;
        Id = id;
    }
}

public class IdentifiedCommandHandler<T, R> :
    IRequestHandler<IdentifiedCommand<T, R>, R>
    where T : IRequest<R> {...}

May i know what's missing?


Solution

  • Adding this resolved my issue.

    builder.RegisterType(typeof(IdentifiedCommandHandler<CreateMessageCommand, bool>))
        .As<IRequestHandler<IdentifiedCommand<CreateMessageCommand, bool>, bool>>()
        .AsImplementedInterfaces();