0

My .Net 7 application has the following issue:

Autofac.Core.DependencyResolutionException: An exception was thrown while activating MyApp.Modules.MyModule.Application.MyModule.UpdateCommand.UpdateCommandHandler.
 ---> Autofac.Core.DependencyResolutionException: None of the constructors found with 'MyApp.Modules.MyModule.Infrastructure.Configuration.AllConstructorFinder' on type 'MyApp.Modules.MyModule.Application.MyModule.UpdateCommand.UpdateCommandHandler' can be invoked with the available services and parameters:
Cannot resolve parameter 'MyApp.Modules.MyModule.Application.Contracts.IMyModule myModule' of constructor 'Void .ctor(Serilog.ILogger, MyApp.Modules.MyModule.Application.Contracts.IMyModule)'.

UpdateCommandHandler.cs (where the issue is occurring)

public class UpdateCommandHandler: ICommandHandler<UpdateCommand>
{
    private readonly IMyModule _myModule;
    private readonly ILogger _logger;

    public UpdateCommandHandler(ILogger logger, IMyModule myModule)
    {
        _myModule = myModule;
        _logger = logger;
    }
    public async Task<Unit> Handle(UpdateCommand request, CancellationToken cancellationToken)
    {
        var foo = await _myModule.ExecuteQueryAsync(new SampleQuery());
        return Unit.Value;
    }
}

Program.cs

...

var builder = WebApplication.CreateBuilder(args);
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(b => b.RegisterModule(new AutofacModules()));

...

I looked at similar issues before posting, such as this, but I do believe I appropriately registered IMyModule in Autofac as MyModule in the following.

AutofacModules.cs

public class AutofacModules: Autofac.Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<MyModule>().As<IMyModule>().InstancePerLifetimeScope();
    }
}

IMyModule.cs

public interface IMyModule
{    
    Task ExecuteCommandAsync(ICommand command);

    Task<TResult> ExecuteQueryAsync<TResult>(IQuery<TResult> query);
}

MyModule.cs

public class MyModule: IMyModule
{    
    public async Task ExecuteCommandAsync(ICommand command)
    {
        await CommandsExecutor.Execute(command);
    }

    public Task<TResult> ExecuteQueryAsync<TResult>(IQuery<TResult> query)
    {
        var scope = MyCompositionRoot.BeginLifetimeScope();
        var mediator = scope.Resolve<IMediator>();
        return mediator.Send(query);
    }
}

AllConstructorFinder.cs

internal class AllConstructorFinder : IConstructorFinder
{
    private static readonly ConcurrentDictionary<Type, ConstructorInfo[]> Cache = new();

    public ConstructorInfo[] FindConstructors(Type targetType)
    {
        var result = Cache.GetOrAdd(targetType, t => t.GetTypeInfo().DeclaredConstructors.ToArray());
        return result.Length > 0 ? result : throw new NoConstructorsFoundException(targetType);
    }
}
Griffin
  • 710
  • 2
  • 15
  • 29
  • 1
    I get the impression you may be over simplifying the example - the exception says you're using a custom constructor finder, for example, which isn't shown. Also, [did you see the trusting docs?](https://autofac.readthedocs.io/en/latest/troubleshooting/exceptions/no-found-constructors-can-be-invoked.html) – Travis Illig Feb 17 '23 at 13:44
  • Added AllConstructorFinder code. I followed the link and found it very helpful, particularly the `container.Resolve()` snippet. Using this snippet, I debugged through my program til I found the issue, which I'll post below. – Griffin Feb 17 '23 at 16:27
  • Glad you figured it out. Also, ARGH AUTOCORRECT ^troubleshooting – Travis Illig Feb 17 '23 at 20:02

1 Answers1

0

In my Program.cs, I had registered MyModule, but, as I have multiple modules with their own containers, I didn't register it in the module's own composition root. By adding the following line, I'm able to include MyModule as a constructor parameter.

MyModuleStartup.cs

...
var containerBuilder = new ContainerBuilder();
...
/* NEW LINE */
containerBuilder.RegisterType<CventModule>().As<ICventModule>().InstancePerLifetimeScope();
...

So lesson here is make sure the component you are using is registered to Autofac root container your module is running directly in. Thanks to @Travis Illig for the troubleshooting link which helped me immensely.

Griffin
  • 710
  • 2
  • 15
  • 29