Autofac.Core.Registration.ComponentNotRegisteredException

13,042

Your code and the exception message clearly show the problem. In summary, your exception message explains that:

The requested service 'ICommandHandler<ICommand>' has not been registered.

In other words, you are requesting an ICommandHandler<ICommand> instead of an ICommandHandler<TestCommand>. This can be seen here:

public void ExecuteCommand(ICommand command)
{
    var handler = cqrsHandlerFactory.GetCommandHandler(command);
    // ...
}

The C# compiler applied type inference to the GetCommandHandler<T> call. So the following code is the actual call:

var handler = cqrsHandlerFactory.GetCommandHandler<ICommand>(command);

You should change the ICrqsBus.ExecuteCommand method to the following:

public void ExecuteCommand<TCommand>(TCommand command)
{
    // You can merge the factory and your CqrsBus. Splitting them is useless.
    var handler = cqrsHandlerFactory.GetCommandHandler<TCommand>();
    // You don't need then null check; Autofac never returns null.
    handler.Handle(command);
}

If you can't make the ExecuteCommand method generic (e.g. because you don't know the command type at compile time), you should build the generic types using the reflection API as follows:

public class CqrsBus : ICqrsBus
{
    private readonly IComponentContext context;

    public CqrsBus(IComponentContext context)
    {
        this.context = context;
    }

    public void ExecuteCommand(ICommand command)
    {
        Type handlerType = typeof(ICommandHandler<>).MakeGenericType(command.GetType());
        dynamic handler = this.context.Resolve(handlerType);
        void handler.Execute((dynamic)command);
    }
}
Share:
13,042
TjDillashaw
Author by

TjDillashaw

Updated on June 13, 2022

Comments

  • TjDillashaw
    TjDillashaw almost 2 years

    Im trying to implement CQRS pattern to my app. So I found how to register all command handlers from assembly here : Autofac resolve dependency in CQRS CommandDispatcher

    But it doesnt work well for me. Here is the code:

            containerBuilder.RegisterAssemblyTypes(assembly)
                .AsClosedTypesOf(typeof(ICommandHandler<>));
    
            containerBuilder.RegisterAssemblyTypes(assembly)
                .AsClosedTypesOf(typeof(IQueryHandler<,>));
    

    Handlers factory

     public class CqrsHandlerFactory : ICqrsHandlerFactory
    {
        private readonly IContainer container;
    
        public CqrsHandlerFactory(IContainer container)
        {
            this.container = container;
        }
    
        public ICommandHandler<TCommand> GetCommandHandler<TCommand>(TCommand command) where TCommand : class, ICommand
        {
            return container.Resolve<ICommandHandler<TCommand>>();
        }
    
        public IQueryHandler<TQuery, object> GetQueryHandler<TQuery>(TQuery query) where TQuery : class, IQuery
        {
            return container.Resolve<IQueryHandler<TQuery, object>>();
        }
    }
    

    Bus

     public class CqrsBus : ICqrsBus
    {
        private readonly ICqrsHandlerFactory cqrsHandlerFactory;
    
        public CqrsBus(ICqrsHandlerFactory cqrsHandlerFactory)
        {
            this.cqrsHandlerFactory = cqrsHandlerFactory;
        }
    
        public void ExecuteCommand(ICommand command)
        {
            var handler = cqrsHandlerFactory.GetCommandHandler(command);
            if (handler == null)
                throw new NotImplementedHandlerException(string.Format("Cannot find handler for {0}", command.GetType()));
            handler.Handle(command);
        }
    
        public TResult RunQuery<TResult>(IQuery query)
        {
            var handler = cqrsHandlerFactory.GetQueryHandler(query);
            if (handler == null)
                throw new NotImplementedHandlerException(string.Format("Cannot find handler for {0}", query.GetType()));
            return (TResult)handler.Handle(query);
        }
    }
    

    Exception

    An exception of type 'Autofac.Core.Registration.ComponentNotRegisteredException' occurred in Autofac.dll but was not handled in user code Additional information: The requested service 'PromocjeWsieciowkach.Messaging.Core.ICommandHandler`1[[PromocjeWsieciowkach.Messaging.Core.ICommand, PromocjeWsieciowkach.Messaging.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' 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.

    Stacktrace

    at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable1 parameters) at Autofac.ResolutionExtensions.Resolve[TService](IComponentContext context, IEnumerable1 parameters) at PromocjeWsieciowkach.Messaging.Factories.CqrsHandlerFactory.GetCommandHandler[TCommand](TCommand command) in C:\Users\Daniel\Desktop\PromocjeWsieciowkach\src\PromocjeWsieciowkach.Messaging\Factories\CqrsHandlersFactory.cs:line 17 at PromocjeWsieciowkach.Messaging.Bus.CqrsBus.ExecuteCommand(ICommand command) in C:\Users\Daniel\Desktop\PromocjeWsieciowkach\src\PromocjeWsieciowkach.Messaging\Bus\CqrsBus.cs:line 17 at PromocjeWsieciowkach.Controllers.PostController.Index() in C:\Users\Daniel\Desktop\PromocjeWsieciowkach\src\PromocjeWsieciowkach\Controllers\PostController.cs:line 20 at lambda_method(Closure , Object , Object[] ) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__28.MoveNext()

    So what i'am doing wrong?

  • Web Dev Guy
    Web Dev Guy over 6 years
    If your run into this problem with nopcommerce check my answer :)